/***************************************************************************
 vecteurs.cpp  -  Librairie d'objets permettant de manipuler des vecteurs
 -------------------
 begin                : ven aug 14 10:25:55 CEST 2000
 copyright            : (C) 2000 by Olivier Langella CNRS UPR9034
 email                : Olivier.Langella@pge.cnrs-gif.fr
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

//#include <strstream>

//using namespace std;

#include"vecteurs.h"

namespace biolib {
namespace vecteurs {

void GetLigneFlot(istream& entree, string & ligne) {
	char car;
	ligne.assign("");
	car = entree.peek();
	while (((car != 10) & (car != 13)) & (entree.good()) & (entree.eof() == 0)) {
		entree.get(car);
		ligne += car;
		car = entree.peek();
	}
	while (((car == 10) | (car == 12) | (car == 13)) & entree.good()
			& (entree.eof() == 0)) {
		entree.get(car);
		car = entree.peek();
	}
}

void ChaineCar::GetLigneFlot(istream& entree) {
	//cerr << "ChaineCar::GetLigneFlot debut" << endl;

	char car;

	assign("");
	car = entree.peek();
	//cerr << "ChaineCar::GetLigneFlot debut " << car << endl;
	while (((car != 10) && (car != 13)) && (entree.good())) {

		entree.clear();

		entree.get(car);

		//cerr << "ChaineCar::GetLigneFlot car" << car << endl;
		assign(*this + car);
		car = entree.peek();
	}
	while (((car == 10) || (car == 13)) && (entree.good())) {
		entree.get(car);
		car = entree.peek();
	}

	//cerr << "ChaineCar::GetLigneFlot fin" << endl;
}

void ChaineCar::assigner(const string& chorigine, signed long deb,
		signed long fin) {
	//assigne seuleument une partie de la chorigine
	// de deb a fin inclus

	signed long i;

	assign("");
	if (deb < 0)
		deb = 0;

	for (i = deb; i <= fin; i++) {
		if (i >= (signed long) chorigine.size())
			break;
		*this += chorigine[i];
		//		cout << chorigine[i];
	}
	//	cout << endl;
}

bool ChaineCar::EstUnChiffre() const {
	unsigned long i;

	//cerr << "ChaineCar::EstUnChiffre()" << endl;
	for (i = 0; i < size(); i++) {
		if ((operator[](i) < 48) || (operator[](i) > 57))
			return (false);
	}

	//cerr << "ChaineCar::EstUnChiffre() vrai" << endl;
	return (true);
}

ChaineCar& ChaineCar::AjEntier(long i) {
	//conversion automatique en base 10 et concaténation
	int unite;
	long facteur;
	char chiffre;
	bool debut(false);

	if (i == 0) {
		this->string::operator+=("0");
	} else
		for (facteur = 1000000; facteur > 0; facteur = facteur / 10) {

			unite = i / facteur;

			if ((debut) || (unite > 0)) {
				debut = true;
				i = i - (unite * facteur);
				chiffre = unite + 48;
				this->string::operator+=(chiffre);
			}
		}
	return (*this);
}

long ChaineCar::GetNbMots() const {
	//retourne le nombre de mots contenus
	// dans la chaine (séparateur= ' ' ou '/t')
	long resultat(0);
	long i, taille;
	bool change(true);
	bool quote(false);

	taille = this->size();

	//cerr << "ChaineCar::GetNbMots()" << *this <<"Fin" << endl;
	for (i = 0; i < taille; i++) {
		if (this->operator[](i) == '\'')
			quote = !(quote);
		if ((quote == false) && (this->operator[](i) > 32)) {
			if (change) {
				//cerr << this->operator[](i) << endl;
				resultat++;
				change = false;
			}
		} else {
			change = true;
		}
	}

	//cerr << *this << endl;
	//cerr << "ChaineCar::GetNbMots()" << resultat << endl;
	return (resultat);
}

void ChaineCar::GetMot(unsigned int numero, string &mot) const {
	//retourne le numeroième mot contenu
	// dans la chaine (séparateur= ' ' ou '/t')
	if (numero < 1) {
		mot = "";
		return;
	}

	unsigned int resultat(0);
	unsigned int i, taille, debut(0), fin(0);
	bool change(true);
	bool quote(false);

	taille = this->size();

	//cerr << "mot:" << *this <<"Fin" << endl;
	for (i = 0; i < taille; i++) {
		//cerr << this->operator[](i) << endl;
		if (this->operator[](i) == '\'') {
			if ((resultat == numero) && (quote)) {
				fin = (i - 1);
				break;
			}
			quote = !(quote);
			if ((resultat == numero) && (quote)) {
				debut = (i + 1);
				//			break;
			}
		}
		if ((quote) || (this->operator[](i) > 32)) {
			//caractere normal
			if (change) {
				change = false;
				resultat++;
				debut = i;
				if (quote)
					debut++;
			}
			fin = i;
		} else {
			if (resultat == numero)
				break;
			change = true;
		}
	}
	fin++;

	if (resultat != numero) {
		mot = "";
		return;
	}

	mot = substr(debut, (fin - debut));
	//cerr << "mot:" << mot <<"Fin" << endl;

}

const Titre& Titre::operator=(const Titre &rval) {
	unsigned long t(rval.size());
	unsigned long i;

	for (i = 0; i < size(); i++) {
		delete vector<ChaineCar*>::operator[](i);
		//		delete at(i);
	}

	erase(begin(), end());
	reserve(t);
	for (i = 0; i < t; i++) {
		push_back(rval.GetTitre(i));
	}
	return (*this);
}

Titre::~Titre() {
	unsigned long i;

	for (i = 0; i < size(); i++) {
		delete vector<ChaineCar*>::operator[](i);
		//		delete at(i);
	}
}

long Titre::Position(const ChaineCar& chaine) const {
	unsigned long i;
	signed long res(-1);

	for (i = 0; i < size(); i++) {
		if (!(chaine.compare(GetTitre(i)))) {
			//cerr << chaine << GetTitre(i) << "_" << endl;
			//		if (chaine.compare(GetTitre(i)) == 0) {
			res = i;
			break;
		}
	}

	return (res);
}
;

void Titre::GetArguments(const string & ligne) {
	//doit se comporter comme le shell
	// sépare les mots, et accepte les ' ou les "
	unsigned int i;
	bool quote(false), vide(false);

	push_back("");

	for (i = 0; i < ligne.size(); i++) {
		if ((quote == false) && ((back().size() > 0) || vide) && ((ligne[i]
				== ' ') || (ligne[i] == '\t'))) {//séparateur
			push_back("");
			vide = false;
		} else {
			if ((ligne[i] == '"') || (ligne[i] == '\'')) {
				if ((quote) && (back().size() == 0))
					vide = true;
				quote = !(quote);
			} else
				back() += ligne[i];
		}
	}
	/*
	 cerr << "Titre::GetArguments(const string & ligne)" << endl;
	 for (i=0; i < size(); i++) {
	 cerr << get_titre(i) << endl;
	 }
	 */
}

bool Titre::operator==(const Titre &rval) {
	// comparaison de deux titres
	unsigned long i;

	if (rval.size() != size())
		return (false);

	for (i = 0; i < size(); i++) {
		if (GetTitre(i).compare(rval.GetTitre(i)) != 0)
			return (false);
	}

	return (true);
}

Titre::Titre(char ** commandes, int nbcommandes) {
	long i;

	for (i = 0; i < nbcommandes; i++) {
		push_back(commandes[i]);
	}
}

/*
 Titre::Titre(const Titre& rval) {

 *this = rval;

 }
 */

void Titre::resize(long nouvtaille) {
	//on efface:
	long i, taille(size());

	for (i = 0; i < taille; i++)
		delete vector<ChaineCar*>::operator[](i);

	//on réalloue
	vector<ChaineCar*>::resize(nouvtaille);
	for (i = 0; i < nouvtaille; i++)
		vector<ChaineCar*>::operator[](i) = new ChaineCar;

}

Titre Titre::operator+(const Titre &rval) const {
	//marche pas...
	long i, taille(rval.size());
	Titre Resultat;

	Resultat = *this;

	for (i = 0; i < taille; i++) {
		//cerr << rval.GetTitre(i);
		Resultat.push_back(rval.GetTitre(i));
	}

	return Resultat;
}

void ChaineCar::fmajus() {
	//convertit la chaine en majuscules
	// après une lecture par exemple
	int taille(size());
	int i;

	for (i = 0; i < taille; i++) {
		if ((operator[](i) > 96) && (operator[](i) < 124))
			operator[](i) = operator[](i) - 32;
	}
}

void ChaineCar::fsupprchiffres() {
	//supprime les chiffres contenu dans une chaine
	// après une lecture par exemple
	int taille(size() - 1);
	int car, i;

	for (i = taille; i >= 0; i--) {
		car = operator[](i);
		if ((car > 47) && (car < 58))
			erase(i, 1);
	}
}

void ChaineCar::fsupprgauche() {
	//supprime les espaces ou tabulations à gauche
	//	unsigned int i;
	//cerr << "ChaineCar::fsupprgauche() [" << (int) operator[](0) << "]" << *this << endl;

	//	i = 0;
	//	while (((operator[](i) == ' ')||(operator[](i) == '\t')) && (i < size())) {
	while (((operator[](0) == ' ') || (operator[](0) == '\t')) && (size() > 0)) {
		//while ((operator[](i) < 33) && (i < size())) {
		erase(0, 1);
		//		i++;
	}
	//cerr << "ChaineCar::fsupprgauche() [" << *this << endl;
}

void ChaineCar::fsupprdroite() {
	//supprime les espaces ou tabulations à droite
	signed int i;

	i = size() - 1;
	while (((operator[](i) == ' ') || (operator[](i) == '\t')) && (i >= 0)) {
		//while ((operator[](i) < 33) && (i >= 0)) {
		erase(i, 1);
		i--;
	}
}

void ChaineCar::fnettoie(const string & mot) {
	//supprime de la chaine de caractere toutes les occurences de "mot"

	int pos;

	pos = find(mot, 0);
	while (pos != -1) {
		replace(pos, mot.size(), "");
		pos = find(mot, 0);
	}
}

unsigned long ChaineCar::GetNbMots(const string & separateur) const {
	//retourne le nombre de mot separes par separateur

	long pos;
	unsigned long iteration(0);

	if (size() == 0)
		return (0);

	pos = find(separateur, 0);
	while (pos != -1) {
		pos = find(separateur, pos + 1);
		iteration++;
	}

	return (iteration + 1);
}

void ChaineCar::GetMot(unsigned int numero, string &mot,
		const string & separateur) const {
	//retourne le nieme mot separe par separateur

	signed int debut(0);
	int fin(-1);
	unsigned int iteration(1);
	int taillesep(separateur.size());
	mot.assign("");

	fin = find(separateur, 0);
	if ((fin == -1) && (numero < 2)) {
		mot.assign(*this);
		return;
	}
	if (fin == -1)
		fin = size();
	while ((debut != -1) && (iteration < numero)) {
		debut = fin + taillesep;
		//cerr << "debut " << debut << endl;
		fin = find(separateur, debut);
		if (fin == -1)
			fin = size();
		//else fin = pos;
		iteration++;
	}

	if (debut == -1)
		return;
	if (debut > (signed int) size())
		return;
	if (fin > (signed int) size())
		return;
	if (debut > fin)
		return;

	mot = substr(debut, (fin - debut));
}

ChaineCar& Titre::GetTitre(long i) const {
	return (*(vector<ChaineCar*>::operator[](i)));
}

void Titre::Suppr(unsigned long pos) {
	if (pos >= size())
		throw Anomalie(1);
	delete (vector<ChaineCar*>::operator[](pos));
	erase(begin() + pos);
}

/** remplacer les occurences de "couper" par "coller" */
void ChaineCar::Remplacer(const string & couper, const string & coller) {

	int pos;

	pos = find(couper, 0);
	while (pos != -1) {
		replace(pos, couper.size(), coller);
		pos = find(couper, 0);
	}
}

int ChaineCar::Position(const string & motif) const {
	return (find(motif, 0));
}

}//namespace biolib {
}//namespace vecteurs {


