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

    supportware
    Copyright (C) 2001-2008 by c.holzheuer
    c.holzheuer@sourceworx.org

    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 <ddstringrow.h>
#include <algorithm>


/**
	Default constructor.
*/

ddstringrow::ddstringrow()
{
}


/**
	Erzeugt eine ddstringrow mit vorgegebener Größe.
	@param size die vorgegebene Größe.
*/

ddstringrow::ddstringrow( size_t asize )
{
	if( asize )
	resize( asize );
}


/**
	Erzeugt eine ddstringrow aus einem char** array.
	@param src Das quell-array. Muss zero terminated sein.
*/

ddstringrow::ddstringrow( const char** src )
{
	create( src );	
}


/**
	Erzeugt eine ddstringrow  aus einem string
	@see create
*/

ddstringrow::ddstringrow( const ddstring& src, const ddstring& sep, size_t minsize )
{
	create( src, sep, false, minsize );
}


/**
	Destructor.
*/

ddstringrow::~ddstringrow()
{

}


/**
	Erzeugt Felder aus einem char** array.
	@param src Das quell-array. Muss zero terminated sein.
*/

void ddstringrow::create( const char** src )
{
	while( *src )
	{
		push_back( ddstring(*src) );
		src++;
	}
}


/**
	Einen string in Felder zerhacken
	Felder werden durch jedes Zeichen in 'sep' getrennt, zB. create( "la;le;lu", ";" )
	Jeder Trenner erzeugt  ein Feld:
	create_lazy("la;;;le",";") erzeugt "la","","","le".
	@param src der quellstring
	@param sep der trenner. Default: " \t" (blank and tab).
	@param keepseps wenn 'true' werden die Trennzeichen mitgespeichert.default: 'false'.
	@see ddstringrow::create_lazy
*/

void ddstringrow::create( const ddstring& src, const ddstring& sep, bool doappend, size_t minsize )
{
	if( !doappend )
		clear();

	size_t beg = 0;
	size_t end = 0;
	size_t offset = sep.size();
	// ein trennzeichen, ein feld (ala otti)
	while ( beg < src.size() )
	{
		end = src.find_first_of( sep, beg );
		if( end == ddstring::npos )
			end = src.size();
  	push_back( src.substr( beg, end - beg ) );
		beg = end + offset;
	}
	if( minsize )
	{
		while( size() < minsize )
			// wieso bitte blank?
			// push_back( " " );
			push_back( "" );
	}
}


/**
	Einen string in Felder zerhacken
*/

void ddstringrow::create_blocks( const ddstring& src, const ddstring& sep, bool doappend )
{
	if( !doappend )
		clear();

	size_t beg = 0;
	size_t end = 0;
	size_t offset = sep.size();
	// ein trennzeichen, ein feld (ala otti)
	while ( beg < src.size() )
	{
		end = src.find( sep, beg );
		if( end == ddstring::npos )
			end = src.size();
  	push_back( src.substr( beg, end - beg ) );
		beg = end + offset;
	}
}
	

/**
	Einen string in Felder zerhacken
	Felder werden durch jedes Zeichen in 'sep' getrennt, zB. create( "la;le;lu", ";" )
	Mehrere Trenner hintereinader erzeugen nur ein Feld:
	create_lazy("la;;;le",";") erzeugt "la","le".
	@param src der quellstring
	@param sep der trenner. Default: " \t" (blank and tab).
	@param keepseps wenn 'true' werden die Trennzeichen mitgespeichert.default: 'false'.
	@see ddstringrow::create
*/

void ddstringrow::create_lazy( const ddstring& src, const ddstring& sep, bool doappend, bool keepseps )
{
	if( !doappend )
		clear();
	ddstring::size_type beg=0, end=0;

	// wiederholte trennzeichen gelten als eins
   beg = src.find_first_not_of( sep );
	while( beg != ddstring::npos )
	{
		// trennzeichen einsammeln
		if( keepseps && beg )
			push_back( src.substr( end, beg - end ) );
		end = src.find_first_of( sep, beg );
		if (end == ddstring::npos)
			end = src.size();
		push_back( src.substr( beg, end - beg ) );
		beg = src.find_first_not_of( sep, end );
	}
	size_t len = end - src.size();
	if ( keepseps && len )
		push_back( src.substr( end, len ) );
}


/**
	Erzeugung aus einem String, dessen Felder die durch newline getrennt sind.
*/

void ddstringrow::create_lines( const char* src, size_t len, bool doappend )
{
	create_lines( ddstring( src, len),  doappend );
}


/**
	Erzeugung aus einem String, dessen Felder die durch newline getrennt sind.
	@param src quelle
	@see ddstringrow::create
	@see ddstringrow::create_lazy
*/

void ddstringrow::create_lines( const ddstring& src, bool doappend )
{
	if( !doappend )
		clear();
	size_t beg=0, end=0;

	// ein trennzeichen, ein feld (ala otti)
	while ( beg < src.size() )
	{
		end = src.find_first_of('\n', beg);
		if (end == ddstring::npos)
			end = src.size();
		size_t asize = end-beg;
		if( src[beg+asize-1]=='\r' )
			--asize;
		if(asize)
			push_back( src.substr( beg,asize ) );
		beg = end + 1;
	}
}


/**
	Einen Eintrag hinten dranhängen.
	@return the internal index of the new entry.
*/

size_t ddstringrow::add( const ddstring& item )
{
	push_back( item );
	return size()-1;
}


/**
	Den Eintrag 'entry' suchen und entfernen.
*/

void ddstringrow::kill_entry( const ddstring& entry )
{
	// ?? was macht das?
	erase( remove( begin(), end(), entry ), end() );
}


/**
	Den Eintrag an Position 'index' löschen.
*/

void ddstringrow::kill_entry( size_t index )
{
	if( index >= size() )
		return;
	erase( begin()+index );
}
	
	
/**
	@returns den index von 'key' oder -1.
*/

int ddstringrow::index_of( const ddstring& key ) const
{
	for( size_t i = 0; i < size(); i++ )
		if( (*this)[i] == key )
			return i;
	return -1;
}
	
	
/**
	Erzeugt einen String aus allen Feldern.
	@param sep		der separator string, zB. ";", default:  ";"
	@param from 	Das erste Feld, default: 0
	@param to		das <b>(nich eingeschlossene!!)</b> Feld. default: npos.
*/

ddstring ddstringrow::join( const ddstring& sep, size_t from, size_t to ) const
{
	ddstring tmp;
	size_t tmp_size = size();
	if( to != ddstring::npos )
		tmp_size = to;
	if( from > tmp_size || tmp_size > size() )
		throw out_of_range( "ddstringrow::join: index 'from' out of range!" );

	for( size_t i = from; i < tmp_size; i++ )
	{
		tmp.append ( (*this)[i] );
		if( !sep.empty() && i != tmp_size - 1)
			tmp.append ( sep );
	}
	return tmp;
}


/**
	Alle Felder nach cout schreiben.
*/

void ddstringrow::dump() const
{
	for( size_t i=0; i<size(); i++ )
	{
		cout << (*this)[i]; 
		if( i < size()-1 ) 
			cout << "\t";
	}
	cout << endl;
}


/**
	stringrep. erzeugen.
*/

ddstring ddstringrow::to_string() const
{
	ddstring result;
	for( size_t i=0; i<size(); i++ )
	{
		result += (*this)[i]; 
		if( i < size()-1 ) 
			result += '|';
	}
	return result;
}
