/*******************************************************************************
 *	BString.h		BString Handling
 *				T.Barnaby,	BEAM Ltd, 29/10/91
 *	Copyright (c) 2012 All Right Reserved, Beam Ltd, http://www.beam.ltd.uk
 *******************************************************************************
 */
#ifndef BSTRING_H
#define BSTRING_H	1

#include	<BTypes.h>
#include	<BRefData.h>
#include	<BList.h>
#include	<BArray.h>
#include	<iostream>

class BError;

class BString {
public:
			BString();
			BString(const BString& string);
			BString(const char* str);
			BString(const char* str, unsigned int len);
			BString(char ch);
			BString(BInt v);
			BString(BUInt v);
			BString(BUInt64 v);
			BString(double v);

			~BString();

	static		BString convert(char ch);			///< Converts char to string
	static		BString	convert(BInt value);			///< Converts int to string
	static		BString	convert(BUInt value);			///< Converts uint to string
	static		BString	convert(double value, int eFormat = 0);	///< Converts double to string
	static		BString	convert(BUInt64 value);			///< Converts long long to string
	static		BString	convertHex(BInt value);			///< Converts int to string as hex value
	static		BString	convertHex(BUInt value);		///< Converts uint to string as hex value

	BString		copy() const;						///< Return an independant copy
	
	int		len() const;						///< Length of string
	const char*	retStr() const;						///< Ptr to char* representation
	char*		retStrDup() const;					///< Ptr to newly malloc'd char*
	int		retInt() const;						///< Return string as a int
	unsigned int	retUInt() const;					///< Return string as a int
	double		retDouble() const;					///< Return string as a double

	int		compare(const BString& string) const;			///< Compare strings
	int		compareWild(const BString& string) const;		///< Compare string to string with wildcards 
	int		compareWildExpression(const BString& string) const;	///< Compare string to space deliminated patterns
	int		compareRegex(const BString& pattern, int ignoreCase = 0) const;		///< Compare strings
	BString&	truncate(int len);					///< Truncate to length len
	BString&	pad(int len);						///< Pad to length len
	void		clear();						///< Clear the string
	
	BString&	toUpper();						///< Convert to uppercase
	BString&	toLower();						///< Convert to lowercase
	BString		lowerFirst();						///< Return string with lowercase  first character
	void		removeNL();						///< Remove if present NL from last char 
	BString		justify(int leftMargin, int width);			///< Justify the string to the given width
	BString		fixedLen(int length, int rightJustify = 0);		///< return string formated to fixed length
	BString		firstLine();						///< Return first line
	BString		translateChar(char ch, BString replace = " ");		///< Translate character converting them to the given string
	BString		reverse() const;					///< Reverse character order
	
	BString		subString(int start, int len) const;			///< Returns substring
	int		del(int start, int len);				///< Delete substring
	int		insert(int start, BString str);				///< Insert substring
	int		append(const BString& str);				///< Append a string
	BString		add(const BString& str) const;				///< Add strings returning result
	BString&	printf(const char* fmt, ...) ;				///< Formated print into the string

	int		find(char ch) const;					///< Find ch in string searching forwards
	int		find(BString str) const;				///< Find string in string searching forwards
	int		findReverse(char ch) const;				///< Find ch in string searching backwards
	
	BString		csvEncode() const;					///< Encode a string for CSV
	BString&	csvDecode(const BString str);				///< Decode a string from CSV
	
	BString		base64Encode() const;					///< Encode a string to base64
	BError		base64Decode(BString& str) const;			///< Decode a string from base64
	

	BList<BString>	getTokenList(BString separators);			///< Break string into tokens 
	BList<BString>	getTokenList(char separator);				///< Break string into tokens 
	BString		removeSeparators(BString separators);			///< Remove any char from sepatators from string
	BString		pullToken(BString terminators);				///< Pull token from start of string
	BString		pullSeparators(BString separators);			///< Pull separators from start of string
	BString		pullWord();						///< Pull a word out of the head of the string
	BString		pullLine();						///< Pull a line out of the head of the string
	BList<BString>	split(char splitChar);					///< Split string into an array based on the character separator

	// Filename operations
	BString		dirname();
	BString		basename();
	BString		extension();
	
	// Misc functions
	BUInt32		hash() const;
	char&		get(int pos);
	const char&	get(int pos) const;
	
	/* Operator functions */
	BString&	operator=(const BString& string);
	char&		operator[](int pos);
	
	int		operator==(const BString& s) const{
				return (compare(s) == 0);
			}
	int		operator==(const char* s) const{
				return (compare(s) == 0);
			}
	int		operator>(const BString& s) const{
				return (compare(s) > 0);
			}
	int		operator>(const char* s) const{
				return (compare(s) > 0);
			}
	int		operator<(const BString& s) const{
				return (compare(s) < 0);
			}
	int		operator<(const char* s) const{
				return (compare(s) < 0);
			}
	int		operator>=(const BString& s) const{
				return (compare(s) >= 0);
			}
	int		operator<=(const BString& s) const{
				return (compare(s) <= 0);
			}
	int		operator!=(const BString& s) const{
				return (compare(s) != 0);
			}
	int		operator!=(const char* s) const{
				return (compare(s) != 0);
			}
	BString 	operator+(const BString& s) const {
				return add(s);
			}
	BString 	operator+(const char* s) const {
				return add(s);
			}
	BString 	operator+=(const BString& s){
				*this = add(s);
				return *this;
			}
	BString 	operator+=(const char* s){
				*this = add(s);
				return *this;
			}
			
	/* Special operators */
	BString 	operator+(char ch) const {
				return add(convert(ch));
			}
	BString 	operator+(BInt i) const {
				return add(convert(i));
			}
	BString 	operator+(BUInt i) const {
				return add(convert(i));
			}
	BString 	operator+(BUInt64 i) const {
				return add(convert(i));
			}
			operator const char* () const {
				return retStr();
			}
#ifdef QSTRING_H
	// QT support
			BString(const QString& str){
#if QT_VERSION >= 0x040000
				init(str.toAscii());
#else
				init(str);
#endif
			}
#ifndef ZAP
			operator QString (){		// QString support
				return QString(retStr());
			}
#endif
#endif

	// For compatibility
	BString		field(int field) const;
	char**		fields();

protected:
	BRefData*	ostr;	

private:
	void		init(const char* str);
	int		inString(int pos) const;
	int		isSpace(char ch) const;
};

/* OStream Functions */
std::ostream& operator<<(std::ostream& o, BString& s);
std::istream& operator>>(std::istream& i, BString& s);

#ifdef BLIST_H
typedef BList<BString>	BStringList;
typedef BArray<BString>	BStringArray;

int bstringListinList(BStringList& l, BString s);

BString blistToString(const BStringList& list);			///< Convert a string list to a comma separated string
BStringList bstringToList(BString str, int stripSpaces = 0);	///< Convert a comma separated string to a string list
BStringList charToList(const char** str);

BString barrayToString(const BStringArray& list);		///< Convert a string array to a comma separated string
BStringArray bstringToArray(BString str, int stripSpaces = 0);	///< Convert a comma separated string to a string array
BStringArray charToArray(const char** str);

#endif

// String conversion functions
void toBString(BString& v, BString& s);
void toBString(BStringList& v, BString& s);
void toBString(BInt32& v, BString& s);
void toBString(BUInt32& v, BString& s);
void toBString(BUInt64& v, BString& s);
void toBString(BFloat64& v, BString& s);
void fromBString(BString& s, BString& v);
void fromBString(BString& s, BStringList& v);
void fromBString(BString& s, BInt32& v);
void fromBString(BString& s, BUInt32& v);
void fromBString(BString& s, BUInt64& v);
void fromBString(BString& s, BFloat64& v);

#endif
