/*FSTRING_____________________________________________________________________
Function Object String class
by Martin Robinson
____________________goal
string manipulation functor collection
____________________philosophy
original data is never to be modified
method only intended to be getter function
new object will reinterpret old one by simulating modification
(hello) + (world) != (helloWorld)
hello == hello
world(hello) = helloworld
(hello) stay intact,
(world) keep hello as ref and add world to the string when asked
http://en.wikipedia.org/wiki/Functional_programming
______________________________________________________________________________
PREPROCESSOR________________________________________________________________*/

#pragma once
#ifndef _FSTRING
#define _FSTRING
//#include <assert.h>
//#include <stdio.h>

/*BASE________________________________________________________________________
dynamic polymorphism in C++
need base class so all object in the collection will be recognised as the alike
contain the only 3 getter function a string really need as virtual
all other getter only need at and size to traverse the string.
following functional paradigm, no setter or mutator is declared
____________________________________________________________________________*/
class baseFstr{
public:
    virtual char at(const int)const;          //virtual return character AT index
    virtual int size()const;                    //virtual return size of the array
    virtual baseFstr * undo()const;             //virtual return previous version 
                                                 //of the string
    //non virtual function that rely on virtual function
    int find(char)const;
    int find(const char *)const;
    int find(const char *, int)const;
    int find(baseFstr*)const;
    int cmp(const char *)const;
    int cmp(const char *, int n)const;
    int cmp(baseFstr*)const;
};
typedef baseFstr fstring;

/*REFERENCE___________________________________________________________________
first string initialisation by reference... mean by reference that the object
does not copy the string but only keep the pointer of the one given, use it
with const char * or if you want a dataflow. This one is more performant
than newFstr version and less secure
____________________________________________________________________________*/
class refFstr : public baseFstr{
    const char * _str;                          //string pointer
    int _size;                                  //size of the string
    void init(const char*);                     //initialise
public:
    refFstr(const char*);                       //constructor
    char at(const int)const;                  //return char at index
    int size()const;                            //return size
};

/*NEW STRING__________________________________________________________________
first string initialisation by copy, this one will copy the string given, so
everything change you make to the original wont affect the object. Slower than
refFstr but more secure
____________________________________________________________________________*/
class nuFstr : public baseFstr{
    char * _str;                                //string pointer
    int _size;                                  //size of the string
    void init(const char*);                     //initialise
public:
    nuFstr(const char*);                        //constructor
    ~nuFstr();                                  //destructor
    char at(const int)const;                  //return char at index
    int size()const;                            //return size
};

/*JOIN________________________________________________________________________
simply append given Fstring object to another
this functor is candidate to deletion (insert is more versatile and do same job)
with dynamic allocation, prefer use of insertNu or insertRef because undo wont
return ins if also needed to delete
____________________________________________________________________________*/
//class joinFstr : public baseFstr{
//    baseFstr * _str,                            //string to modify
//            * _ins;                             //string to insert
//    void init(baseFstr*, baseFstr*);            //initialise
//public:
//    joinFstr(baseFstr*, baseFstr*);             //constructor
//    char at(const int);                  //return char at index
//    int size()const;                            //return size
//    baseFstr * undo()const;                     //return previous string before join
//};

/*INSERT______________________________________________________________________
insert string into another
three version is available
with already declared Fstring
with given char* by copy  more secure slow one
with given char* by ref   non secure fast one
____________________________________________________________________________*/
class insertSubFstr : public baseFstr{
    baseFstr * _str,                            //string to modify
            * _ins;                             //string to insert
    int _from,                                  //start of the insertion
        _to;                                    //end of the insertion
    void init(baseFstr*, baseFstr*, int, int);  //initialise
public:
    insertSubFstr(baseFstr*, baseFstr*, int, int);
    insertSubFstr(baseFstr*, baseFstr*, int);   //constructor
    char at(const int)const;                  //return char at index
    int size()const;                            //return size
    baseFstr * undo()const;                     //return previous fstring
                                                //before insert
};

class insertNuFstr : public baseFstr{
    baseFstr * _str;                            //string to modify
    char * _ins;                                //insertion pointer
    int _from,                                  //start of the insertion
        _to,                                    //end of the insertion
        _insSize;                               //size of the insertion
    void init(baseFstr*, const char*, int, int);//initialise
public:
    insertNuFstr(baseFstr*, const char*, int, int);
    insertNuFstr(baseFstr*, const char*, int);  //constructor
    ~insertNuFstr();
    char at(const int)const;                  //return char at index
    int size()const;                            //return size
    baseFstr * undo()const;                     //return previous fstring
                                                //before insert
};

class insertRefFstr : public baseFstr{
    baseFstr * _str;                            //string to modify
    const char * _ins;                          //insertion pointer
    int _from,                                  //start of the insertion
        _to,                                    //end of the insertion
        _insSize;                               //size of the insertion
    void init(baseFstr*, const char*, int, int);//initialise
public:
    insertRefFstr(baseFstr*, const char*, int, int);
    insertRefFstr(baseFstr*, const char*, int); //constructor
    char at(const int)const;                  //return char at index
    int size()const;                            //return size
    baseFstr * undo()const;                     //return previous fstring
                                                //before insert
};

/*TRIM________________________________________________________________________
remove all character between two index
____________________________________________________________________________*/
class trimFstr : public baseFstr{
    baseFstr * _str;                            //string to modify
    int _from,                                  //start of the triming
        _to;                                    //end of the triming
    void init(baseFstr*, int, int);             //initialise
public:
    trimFstr(baseFstr*, int, int);              //constructor
    char at(const int)const;                  //return char at index
    int size()const;                            //return size
    baseFstr * undo()const;                     //return previous fstring
                                                //before trim
};

/*SUB_STRING__________________________________________________________________
return sub string between two index
____________________________________________________________________________*/
class subFstr : public baseFstr{
    baseFstr * _str;                            //string to modify
    int _from,                                  //start of the substring
        _to;                                    //end of the substring
    void init(baseFstr*, int, int);             //initialise
public:
    subFstr(baseFstr*, int, int);               //constructor
    char at(const int)const;                  //return char at index
    int size()const;                            //return size
    baseFstr * undo()const;                     //return orginal fstring
                                                //that this sub came from
};

/*____________________________________________________________________________
____________________________________________________________________________*/
#endif
