#ifndef Str_h
#define Str_h

extern "C" double atof (const char *);

#pragma interface

class Str {

protected:

	unsigned long int len;
	unsigned long int alloc_len;
	char * adr;
	
	void expand(void);
	void resize(unsigned long newlen);
	
	char dummy[3]; // für long-alignment!
	
	inline char upper(char c) {
		return ('a' <= c && c <= 'z')? c+('A'-'a') : c;
	}
	
	inline char lower(char c) {
		return ('A' <= c && c <= 'Z')? c-('A'-'a') : c;
	}
	
	static const char empty_string;
	
public:

	bool fail;
	
	// ==== Constructors =====
	
	Str(unsigned long length);
	Str(const char * text);
	Str(const char * text, unsigned long length);

	Str(const Str & orig);
	inline Str(void) : len(0), alloc_len(0), adr((char *)&empty_string), fail(0) { };
	
	inline ~Str(void) {
		if (alloc_len) delete [] adr;
	};
	
	// ===== operators ======
	
	const Str & operator=(const Str & string);
	
	int operator==(const Str & rv) const;
	inline int operator!=(const Str & rv) const {
		return !(Str::operator==(rv));
	};
	
	int operator==(const char * p) const;
	inline int operator!=(const char * p) const {
		return !(Str::operator==(p));
	};
	 
	int operator<(const Str & rv) const;
	inline int operator>=(const Str & rv) const {
		return !(operator<(rv));
	};
	int operator>(const Str & rv) const;
	inline int operator<=(const Str & rv) const {
		return !(operator>(rv));
	};
	
	int operator<(const char * p) const;
	inline int operator>=(const char * p) const {
		return !(operator<(p));
	};
//	int operator>(const char * p) const;
//	inline int operator<=(const char * p) const {
//		return !(operator>(p));
//	};

	// ====== casting ======
	
	inline operator const char *() const {
		return (const char *) adr;
	}
	
	inline operator const unsigned char *() const {
		return (const unsigned char *) adr;
	}

	inline operator char *() const {
		return adr;
	}
	
	inline operator unsigned char *() const {
		return (unsigned char *) adr;
	}
	
	// ====== subset-functions ======
	
	Str sub(unsigned long from, unsigned long to) const;
	inline Str before(unsigned long to) const {
		return sub(0,to);
	};
	inline Str after(unsigned long from) const {
		return sub(from+1,len);
	};
	inline Str left(unsigned long chars) const {
		return sub(0,chars);
	};
	inline Str right(unsigned long chars) const {
		return sub(len-chars, len);
	};
	
	// ====== arithmetic functions =========

	Str operator+(const Str & rv) const;
	Str operator+(char rv) const;
	
	inline Str operator+=(char c) {
		if (len >= alloc_len) expand();
		if (len < alloc_len) {
			*(adr+len) = c;
			len++;
			*(adr+len) = 0;
		}
		return *this;
	};
	Str operator+=(const Str & rv);
	
	// ====== searching functions =======
	
	unsigned long index(char match, unsigned long offset = 0) const;
	unsigned long index(const Str & match, unsigned long offset = 0) const;
	unsigned long rindex(char match, unsigned long offset = 0) const;
	
	// ======= misc functions =======
	
	void clear (void);	
	
	int compare (const Str & rv) const;
	
	inline char * chrptr(void) const { return adr; };
	
	inline unsigned long length(void) const { return len; };
	
	inline char chr(unsigned long offset) const {
		return *(adr+offset);
	};
	
	void fill(char fill = 0x20);
	
	unsigned long val(void) const;
	unsigned long long vall(void) const;
	double fval(void) const {
		return atof(adr);
	}
	long sval(void) const;
	long long svall(void) const;
	
	Str next_word(void);
	
	Str next_line(void);
	
	Str & to_upper(void);
	Str & to_lower(void);

	// will not recognize C-style escapes, only octal "\xxx" style
	void implode_escape_sequences(void);
	
};

Str operator+(const char * lv, const Str & rv);

Str NtoStr(unsigned long val, short int width = 0);
Str SNtoStr(long val, short int width = 0);
Str NtoHex(unsigned long val, unsigned short width = 0);
Str FtoStr(double val);
Str LtoStr(long);

#include <iostream.h>

ostream & operator<< (ostream & o, const Str & s);

istream & operator>> (istream & i, Str & s);

class BOstream;
BOstream & operator<< (BOstream & o, const Str & s);

class BIstream;
BIstream & operator>> (BIstream & i, Str & s);

#endif /* Str_h */


syntax highlighted by Code2HTML, v. 0.9.1