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

#ifndef _ATOMS_LISTS
  #define _ATOMS_LISTS
#endif

#define LISTS_VERSION (0x100*0 | 20)

#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 list
class list {
protected: char **pstr;			///< String pointer array.
	   unsigned NumAlloc;		///< Number of allocated slots for strings.
	   unsigned NumUsed;		///< Number of actually used strings.
//	   void resize(int NewMaxlen);

   public: explicit list(int len);	//explicit is expanded to private: for obsolette compilers
   public: list(void) {NumAlloc=NumUsed=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 unsigned i) const {if(i>=NumUsed) return(NULL); return(pstr[i]);}
//je potreba prepsat IN!!, pridat metodu FindElement()
	   int operator IN(const char *) const;
	   unsigned length(void) const		      {return(NumUsed);}
           int isEmpty(void) const		      {return(NumUsed<=0);}

	   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(NumUsed!=l.NumUsed?0:ListCmp(*this,l)==0);}
	   int operator!=(const list &l) const        {return(NumUsed!=l.NumUsed?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(NumUsed>1) Qsort(sorter,pstr,0,NumUsed-1);};

/* friend functions */
	   friend int operator IN(const char *str,const list &l);
	   friend int operator IN(const list &l1,const list &l2);
	   friend unsigned length(const list &l)		{return(l.NumUsed);}
	   friend int AddSTRSorted(list & l,TSorter sorter, const char *str, int AllowDupl);
	   friend int MoveSTR(list & l, char *str);
	   friend unsigned MoveSTRPos(list & l, char *str, unsigned 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;
	   };

int AddSTRSorted(list & l,TSorter sorter, const char *str, int AllowDupl=0);


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(const char **data,int count)  {pstr=const_cast<char**>(data);NumUsed=count;};  //NumAlloc=0;
        const_list(const const_list &cl) {pstr=cl.pstr;NumUsed=cl.NumUsed;}
	~const_list()			   {pstr=NULL;}

        const_list &operator=(const const_list &cl) {pstr=cl.pstr;NumUsed=cl.NumUsed;return *this;}
	};


//Related functions to the class list

#ifdef Streams
 #ifdef IOSTREAM_H_ONLY
  #include<iostream.h>
  ostream &operator<<(ostream &xout, const list & s);
 #else
  #include<iostream>
  std::ostream &operator<<(std::ostream &xout, const list & s);
  //istream &operator>>(istream &, list & s);
 #endif
#endif


#endif
