/*******************************************************
* Unit:    lists             release 0.15              *
* Purpose: general manipulation with list of strings   *
* Licency: GPL or LGPL                                 *
* Copyright: (c) 1998-2019 Jaroslav Fojtik             *
********************************************************/
#ifndef __Lists_h
#define __Lists_h

#ifndef _ATOMS_LISTS
  #define _ATOMS_LISTS
#endif


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


#ifndef No_Memory
 #define No_Memory  0x1
#endif
#define Bad_Number  0x2
#define Bad_Size    0x3
#define Bad_Item    0x4
#define Unsorted    0x5

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

typedef int (*TSorter)(const char *s1,const char *s2);
void Qsort(TSorter sorter, char **item, int d, int h);


class sortedlist;

class list;
class temp_list;
class const_list;

// Main definition part of Class String
class list {
protected: int numalloc;
           char **pstr;
	   int number;
//	   void resize(int NewMaxlen);

   public: explicit list(int len);	//explicit is expanded to private: for obsolette compilers
   public: list(void) {numalloc=number=0;pstr=NULL;};
	   list(const char *str);
	   list(const list &l);
	   list(temp_list &l);
	   list(const char* const* data, int count);
	   ~list(void)				      {erase();};

           char ** operator()() const                 {return(pstr);};
//	   operator const char **() const             {return(pstr);};
	   inline char *operator[](const int i) const {if(i>=number) return(NULL); return(pstr[i]);}
//je potreba prepsat IN!!, pridat metodu FindElement()
	   int operator IN(const char *) const;
	   int length(void) const		      {return(number);}

	   list &operator=(const char *str);
	   list &operator=(const list &l);
	   list &operator=(temp_list &l);

           friend int ListCmp(const list &l1,const list &l2);
	   int operator==(const list &l) const        {return(number!=l.number?0:ListCmp(*this,l)==0);}
	   int operator!=(const list &l) const        {return(number!=l.number?1:ListCmp(*this,l));}
           int operator>(const list &l) const         {return(ListCmp(*this,l)>0);}
	   int operator>=(const list &l) const        {return(ListCmp(*this,l)>=0);}
	   int operator<(const list &l) const         {return(ListCmp(*this,l)<0);}
	   int operator<=(const list &l) const        {return(ListCmp(*this,l)<=0);}

	   int operator+=(const char *str);
	   int operator+=(const list &l);
	   friend temp_list operator+(const list &l1, const list &l2);
	   friend temp_list operator+(const list &l1, const char *str);
	   friend temp_list operator+(const char *str, const list &l2);

           friend temp_list operator-(const list &l1, const char *str);
	   friend temp_list operator-(const list &l1, const list &l2);

	   int operator|=(const list &l);
	   int operator|=(const char *str);
	   friend temp_list operator|(const list &l1,const list &l2);
	   friend temp_list operator|(const list &l1,const char *str);

	   void sort(TSorter sorter) {if(number>1) Qsort(sorter,pstr,0,number-1);};

/* friend functions */
	   friend int operator IN(const char *str,const list &l);
	   friend int operator IN(const list &l1,const list &l2);
	   friend int length(const list &l)		{return(l.number);}
	   friend int AddSTRSorted(list & l,TSorter sorter, const char *str, int AllowDupl=0);
	   friend int MoveSTR(list & l, char *str);
	   friend int MoveSTRPos(list & l, char *str, int Pos);
	   friend int RemoveDups(sortedlist & l);

	   void erase();
	   int check();

	   friend int check(list &l)	{return(l.check());};
	   friend void erase(list &l)	{l.erase();};

	   friend int operator IN(const char *str,const sortedlist &l);
	   friend class temp_list;
	   friend class const_list;
	   };


class sortedlist:public list {
	   TSorter sorter;

public:	   sortedlist(void) {sorter=NULL;};
	   sortedlist(const list &l):list(l) {sorter=NULL;};
	   sortedlist(const char *str):list(str) {sorter=NULL;};
	   sortedlist(TSorter NewSorter) {sorter=NewSorter;};

	   void AddSorter(TSorter NewSorter) {sorter=NewSorter;};

	   sortedlist &operator=(const list &l) {*(list*)this=l;if(sorter!=NULL) sort(sorter); return(*this);};
	   sortedlist &operator=(const sortedlist &l) {*(list*)this=l;if(sorter!=NULL && l.sorter!=sorter) sort(sorter); return(*this);};

	   int operator+=(const char *str)  {return(AddSTRSorted(*this,sorter,str,1));};
	   int operator|=(const char *str)  {return(AddSTRSorted(*this,sorter,str,0));};

/* friend functions */
	   friend int operator IN(const char *str,const sortedlist &l);
	   };


//Internal speedup class - do not use it!
class temp_list:public list
	{
public: temp_list(int n):list(n) {};
	temp_list() {};
	temp_list(temp_list & l):list(l) {};
	temp_list(const list & l):list(l) {};
	temp_list(const char *str):list(str) {};
	};


//Constant list could be feed by char** array
class const_list:public list
	{
protected:	//Disable access to these operators
	int operator+=(const char *str)	   {return(-1);};
	int operator+=(const list &l)	   {return(-1);};
	int operator|=(const list &l)	   {return(-1);};
	int operator|=(const char *str)	   {return(-1);};
	void erase()	{};

public: const_list(char **data,int count)  {pstr=data;numalloc=0;number=count;};
	~const_list()			   {pstr=NULL;}
	};


//Related functions to the class list

#ifdef Streams
#include<iostream.h>
ostream &operator<<(ostream &xout, const list &l);
//istream &operator>>(istream &, list &l);
#endif


#endif
