/***************************************************
* unit:    strings           release 0.25          *
* purpose: general manipulation with text strings  *
* Licency: GPL or LGPL                             *
* Copyright: (c) 1998-2022 Jaroslav Fojtik         *
****************************************************/
/* NOTE: strings.h clashes with standard headers, thus stringa.h */
#ifndef __Stringa_h
#define __Stringa_h

#ifndef __Common_H_INCLUDED
  #include "common.h"
#endif


#ifdef __string_already_used
  #define string bbstring
#endif

#ifndef toupper
 #include <ctype.h>
#endif

#ifdef Streams
 #include <iostream.h>
#endif

#ifndef No_Memory
 #define No_Memory    0x1
#endif
#define Bad_Length   0x2
#define Bad_MaxLen   0x3
#define Wrong_String 0x4
#define Unterminated 0x5
#define IntOverflow  0x6

#ifndef IN
 #define IN %
#else
 #undef IN
 #define IN %
#endif


#ifdef __cplusplus
#include "std_str.h"

extern "C++" {

// Main definition part of Class String
class string;
#ifdef USE_TEMP_STRINGS
class temp_string;
#else
  #ifdef __string_already_used
    #define temp_string bbstring
  #else
    #define temp_string string
  #endif
#endif



class string {
protected:static char Dummy;
	  char *ch;
	  unsigned maxlen;
	  unsigned size;

	  void resize(unsigned int NewMaxlen);

public:   explicit string(unsigned len);	//explicit is expanded to private: for obsolette compilers
public:   string(void)				{size=maxlen=0;ch=0;};
	  string(char c);
	  string(const char *str);
	  string(const string &s);
#ifdef USE_TEMP_STRINGS
	  string(temp_string &s);
          string(temp_string *s);
#endif
	  string(const char *str, int i);
	  ~string(void)				{erase();};
	  char *operator()() const    		{return ch;}
	  operator const char *() const		{return ch;}
	  char & operator *() const		{if(ch!=NULL && size>0) return ch[0]; return(Dummy=0);}
	  string &operator=(char c);
	  string &operator=(const char *str);
	  string &operator=(const string &s);
#ifdef USE_TEMP_STRINGS
	  string &operator=(temp_string &s);
#endif
	  string &operator=(int i)		{return(*this=(char)i);};
	  string &operator=(long l);
	  string &operator=(float f)		{return(*this=(double)f);};
	  string &operator=(double d);

	  inline char &operator[](const unsigned int i) const {if(i>=size) return(Dummy=0); return(ch[i]);}
	  inline char &operator[](const unsigned long i) const {if(i>=size) return(Dummy=0); return(ch[i]);}
	  inline char &operator[](const int i) const {if((unsigned)i>=size || i<0) return(Dummy=0); return(ch[i]);}
	  inline char &operator[](const long i) const {if((unsigned long)i>=size || i<0) return(Dummy=0); return(ch[i]);}
#ifdef FIX_LONGLONG
	  inline char &operator[](const unsigned long long i) const {if(i>=size) return(Dummy=0); return(ch[i]);}
#endif

//	  char *operator IN(const char *str) {return(StrStr(str,ch));}
	  friend char *operator IN(const char *str,const string &s) {return(StrStr(s.ch,str));}
	  friend char *operator IN(char c, const string & s) {return(StrChr(s.ch,c));}
//	  friend char *operator IN(const string &s,const char *str) {return(StrStr(str,s.ch));}

	  int operator==(char c) const		{return(!ChStrCmp(c,*this));}
	  int operator!=(char c) const		{return(ChStrCmp(c,*this));}
	  int operator>(char c) const		{return(ChStrCmp(*this,c)>0);}
	  int operator<(char c) const		{return(ChStrCmp(*this,c)<0);}
	  int operator>=(char c) const		{return(ChStrCmp(*this,c)>=0);}
	  int operator<=(char c) const		{return(ChStrCmp(*this,c)<=0);}

	  int operator==(const string &s) const	{return(!StrCmp(ch,s.ch));}
	  int operator!=(const string &s) const	{return(StrCmp(ch,s.ch));}
	  int operator>(const string &s) const	{return(StrCmp(ch,s.ch)>0);}
	  int operator<(const string &s) const	{return(StrCmp(ch,s.ch)<0);}
	  int operator>=(const string &s) const	{return(StrCmp(ch,s.ch)>=0);}
	  int operator<=(const string &s) const	{return(StrCmp(ch,s.ch)<=0);}

	  int operator==(const char *str) const	{return(!StrCmp(ch,str));}
	  int operator!=(const char *str) const	{return(StrCmp(ch,str));}
	  int operator>(const char *str) const	{return(StrCmp(ch,str)>0);}
	  int operator<(const char *str) const	{return(StrCmp(ch,str)<0);}
	  int operator>=(const char *str) const	{return(StrCmp(ch,str)>=0);}
	  int operator<=(const char *str) const	{return(StrCmp(ch,str)<=0);}

	  friend int operator==(const char *str,const string &s) {return(!StrCmp(str,s.ch));}
	  friend int operator!=(const char *str,const string &s) {return(StrCmp(str,s.ch));}
	  friend int operator>(const char *str,const string &s)  {return(StrCmp(str,s.ch)>0);}
	  friend int operator<(const char *str,const string &s)  {return(StrCmp(str,s.ch)<0);}
	  friend int operator>=(const char *str,const string &s) {return(StrCmp(str,s.ch)>=0);}
	  friend int operator<=(const char *str,const string &s) {return(StrCmp(str,s.ch)<=0);}

	  friend int operator==(char c,const string &s) {return(!ChStrCmp(c,s));}  ///!!!!!Slow!!!
	  friend int operator!=(char c,const string &s) {return(ChStrCmp(c,s));}
	  friend int operator>(char c,const string &s)  {return(ChStrCmp(c,s)>0);}
	  friend int operator<(char c,const string &s)  {return(ChStrCmp(c,s)<0);}
	  friend int operator>=(char c,const string &s) {return(ChStrCmp(c,s)>=0);}
	  friend int operator<=(char c,const string &s) {return(ChStrCmp(c,s)<=0);}

	  string &ToUpper(void);
	  string &ToLower(void);
	  string &trim(void);
	  char *ExtractString()	{char *str=ch;ch=NULL;size=maxlen=0;return(str);}

	  void erase(void);
	  int check(void);
          int isEmpty(void) const {return(size<=0 || ch==NULL);}
          int length(void) const {return(size);}

	  friend string & append(string & s1, char c);
	  friend string & append(string & s1, const char *str);
	  friend string & append(string & s1, const string & s2);
	  friend string & append(string & s1, long l);
	  friend string & append(string & s1, double d);

	  friend temp_string operator+(const string & s, char c);
	  friend temp_string operator+(const string & s1, const char *str);
	  friend temp_string operator+(const string & s1, const string & s2);
	  friend temp_string operator+(const char *str, const string & s2);
	  friend temp_string operator+(char c, const string & s);
	  string & operator+=(char c)		{return append(*this,c);};
	  string & operator+=(const char *str)	{return append(*this,str);};
	  string & operator+=(const string &s)	{return append(*this,s);};
#ifdef USE_TEMP_STRINGS
	  string & operator+=(const temp_string &s);
#endif

	  friend temp_string multiply(const string& s, unsigned n);
	  //friend temp_string operator*(const string& s, unsigned n);
	  //friend temp_string operator*(unsigned n, const string & s);
	  string &operator*=(unsigned n);

	  friend string &operator<<(string &strout, const string &s) {return append(strout,s);};
	  friend string &operator<<(string &strout, const char *str) {return append(strout,str);};
	  friend string &operator<<(string &strout, char c)   {return append(strout,c);};
	  friend string &operator<<(string &strout, int i)    {return append(strout,(long)i);};
	  friend string &operator<<(string &strout, long l)   {return append(strout,l);};
	  friend string &operator<<(string &strout, float f)  {return append(strout,(double)f);};
	  friend string &operator<<(string &strout, double d) {return append(strout,d);};

	  friend int ChStrCmp(char c, const string & s);  //-1  c<s  0 c==s  1 c>s
	  friend int ChStrCmp(const string & s,char c) {return(-ChStrCmp(c,s));};  //-1  c>s  0 c==s  1 c<s
	  friend int length(const string &s) {return(s.size);}

	  friend int check(string &s)	{return(s.check());};
	  friend void erase(string &s)	{s.erase();};

//Overloading of well known C string functions
	  friend temp_string del(const string &s,int from, int len=1);
	  friend temp_string insert(const string &s,const string &s2,int position);
	  inline char *strchr(const string &s1,char c) {return(StrChr(s1.ch,c));};
	  inline char *strstr(const string &s1,const string &s2) {return(StrStr(s1.ch,s2.ch));};
	  inline const char *strstr(const string &s1,const char *str2) {return(StrStr(s1.ch,str2));};
	  inline const char *strstr(const char *str1,const string &s2) {return(StrStr(str1,s2.ch));};
	  inline int strcmp(const string &s1,const string &s2) {return(StrCmp(s1.ch,s2.ch));};
	  inline int strcmp(const string &s1,const char *str2) {return(StrCmp(s1.ch,str2));};
	  inline int strcmp(const char *str1,const string &s2) {return(StrCmp(str1,s2.ch));};
	  friend int strlen(const string &s) {return(s.size);}
	  friend temp_string ToUpper(const char *str);
	  friend temp_string ToLower(const char *str);

//speedup class interface
#ifdef USE_TEMP_STRINGS
	  friend class temp_string;
#endif
	  friend temp_string replacesubstring(const string & s, const string & substring, const string & newsubstring );
	  friend temp_string replacesubstring(const string & s, const char *substring, const char *newsubstring );
	  friend temp_string replacesubstring(const string & s, const char *substring, const string & newsubstring );
	  friend temp_string replacesubstring(const string & s, const string & substring, const char *newsubstring );

// Printer
          int printf(const char* format, ...);
          int cat_printf(const char* format, ...);
	  };


#ifdef USE_TEMP_STRINGS
/// Internal speedup class - do not use it! When string is constructed from
/// temp_string it removes its content.
class temp_string
	{
public: char *ch;
	unsigned maxlen;
	unsigned size;	

	temp_string()			 {ch=NULL; maxlen=size=0;};
	temp_string(char c);
	temp_string(temp_string & s)     {ch=s.ch; maxlen=s.maxlen; size=s.size; s.ch=NULL;s.maxlen=s.size=0;};
	explicit temp_string(string & s) {ch=s.ch; maxlen=s.maxlen; size=s.size; s.ch=NULL;s.maxlen=s.size=0;};
	temp_string(const char *str);
	temp_string(const char *str,int i);

	temp_string &operator=(temp_string &s);
	const char *operator()() const    	{return ch;}
	//operator char *()		{return ch;}	

	int isEmpty(void) const {return(size<=0 || ch==NULL);}
        int length(void) const {return(size);}

	/*int operator==(char c) const		{return(!ChStrCmp(c,*this));}
	int operator!=(char c) const		{return(ChStrCmp(c,*this));}
	int operator>(char c) const		{return(ChStrCmp(*this,c)>0);}
	int operator<(char c) const		{return(ChStrCmp(*this,c)<0);}
	int operator>=(char c) const		{return(ChStrCmp(*this,c)>=0);}
	int operator<=(char c) const		{return(ChStrCmp(*this,c)<=0);}*/
	
	int operator==(const char *str) const	{return(!StrCmp(ch,str));}
	int operator!=(const char *str) const	{return(StrCmp(ch,str));}
	int operator>(const char *str) const	{return(StrCmp(ch,str)>0);}
	int operator<(const char *str) const	{return(StrCmp(ch,str)<0);}
	int operator>=(const char *str) const	{return(StrCmp(ch,str)>=0);}
	int operator<=(const char *str) const	{return(StrCmp(ch,str)<=0);}

        int operator==(const string &s) const	{return(!StrCmp(ch,s.ch));}
	int operator!=(const string &s) const	{return(StrCmp(ch,s.ch));}
	int operator>(const string &s) const	{return(StrCmp(ch,s.ch)>0);}
	int operator<(const string &s) const	{return(StrCmp(ch,s.ch)<0);}
	int operator>=(const string &s) const	{return(StrCmp(ch,s.ch)>=0);}
	int operator<=(const string &s) const	{return(StrCmp(ch,s.ch)<=0);}
	};
#endif


//Inline functions for class string that requires temp_string defined
inline temp_string operator*(const string& s, unsigned n) {return multiply(s,n);}
inline temp_string operator*(unsigned n, const string& s) {return multiply(s,n);}
inline string & string::operator*=(unsigned n) {*this=multiply(*this,n);return(*this);}
#ifdef USE_TEMP_STRINGS
inline string & string::operator+=(const temp_string &s) {return append(*this,s.ch);}
#endif

//Related functions to the class string
temp_string copy(const string &s,int from, int len);
temp_string trim(const string & s);
temp_string replacesubstring(const string & s, const string & substring, const string & newsubstring);
temp_string replacesubstring(const string & s, const char *substring, const char *newsubstring);
inline temp_string replacesubstring(const string & s, const string & substring, const char *newsubstring)
		{return(replacesubstring(s,substring(),newsubstring));}
inline temp_string replacesubstring(const string & s, const char *substring, const string &newsubstring)
		{return(replacesubstring(s,substring,newsubstring()));}
temp_string ToUpper(const char *str);
temp_string ToLower(const char *str);
#ifdef USE_TEMP_STRINGS
inline temp_string ToUpper(const temp_string & ts) {return ToUpper(ts.ch);}
inline temp_string ToLower(const temp_string & ts) {return ToLower(ts.ch);}
#endif

#ifdef Streams
ostream &operator<<(ostream &xout, const string &s);
//istream &operator>>(istream &, string &);
#endif

} // extern "C++"
#endif	/* __cplusplus */

#endif
