/****************************************************************************
*
*  var.hpp
*
*  Create:  Dec 12 2004
*  Update:  Sep 23 2005
*  © Jan-Erik Lärka 2004 - 2005
*
****************************************************************************/
#ifndef
 VAR_HPP
#define VAR_HPP
#include <iostream>
#include <stdlib.h>
#include <rexxsaa.h>

using namespace std;

enum Calc { Add, Sub, Mult, Div };

class var {
   private:
      char *string;     // Pointer to array that hold the string.
      int alloc_size;   // Maintained value to indicate size of array.
      bool static_size; // Maintained value to indicate if array use a static size.
   public:
/** Constructor alt. 1
 * var( size, <static size> )
 *
 * This constructor create the new object that can hold
 * a string of specified size. Additionally it's possible
 * to specify if the string/array should be static in size
 * or
dynamically resizeable by the class.
 * Parameters:
 *                slength - number of characters (mandatory)
 *                s_size - static size (optional, FALSE by default)
 */

      var( int slength, bool s_size = false ) : static_size( s_size ) {
         if ( slength < 0 ) slength = 0;
         string = new char[ slength + 1 ];
         for( int i = 0; i <= slength; i++ ) string[ i ] = '\0';
         alloc_size = slength;
      };
/** Constructor alt. 2 (Default constructor too)
 * var( <s>, <size>, <static size> )
 *
 * This constructor create the new object that can hold
 * a string of specified size. Additionally it's possible
 * to specify if the string/array should be dynamically
 * resizeable. If no parameters used it act as default
 * constructor and just prepare for futher use.
 * Parameters:
 *                s - string to set at creation (optional)
 *                slength - number of characters (optional)
 *                s_size - static size (optional, FALSE by default)
 */
      var( const char *s = "", int slength = 0, bool s_size = false ) : static_size( s_size ) {
         int i = 0, slength2 = 0;
         if ( slength < 0 )
            slength2 = slength = -slength;
         else if ( s[ 0 ] != NULL ) while ( s[ slength2 ] != '\0' ) slength2++;
         slength = ( slength == 0 ) ? slength2 : slength;
         string = new char[ slength + 1 ];
         if ( s[ 0 ] != NULL ) for( ; i < slength2 && i < slength; i++ ) string[ i ] = s[ i ];
         for( ; i <= slength; i++ ) string[ i ] = '\0';
         alloc_size = slength;
      };
/** Copy constructor
 * var( class, <static size> )
 *
 * This copy constructor copy contence so it doesn't point to
 * same address space. Additionally it's possible to specify
 * if the target string/array should be dynamically resizeable.
 * Parameters:
 *                v - variable of class var with string (mandatory)
 *                s_size - static size (optional, FALSE by default)
 */
      var( const var& v, bool s_size = false ) : static_size( s_size ) {
         int slength = v.len();
         string = new char[ slength + 1 ];
         for( int i = 0; i < slength; i++ ) string[ i ] = v.string[ i ];
         string[ slength ] = '\0';
         alloc_size = slength;
      };
/** Destructor
 * ~var()
 *
 * Destructor used to destroy allocated object and clean up memory.
 * Parameters:
 *                none
 */
      ~var() { delete [] string; }

/* Methods (Member functions) for class */
      friend int max( int i, int i2 ) { return i > i2 ? i : i2; } // Handle only 2 params, possible to improve
      friend double max( double d, double d2 ) { return d > d2 ? d : d2; } // just add default values to more params
      friend double max( int i, double d ) { return d > i ? d : i; } // and change calculation routine.
      friend double max( double d, int i ) { return i > d ? i : d; }
      friend int min( int i, int i2 ) { return i < i2 ? i : i2; }
      friend double min( double d, double d2 ) { return d < d2 ? d : d2; }
      friend double min( int i, double d ) { return d < i ? d : i; }
      friend double min( double d, int i ) { return i < d ? i : d; }
      bool isAutoResizable() const { return !static_size; } // Return value indicating wheter the array can be resized
      bool isStaticInSize() const { return static_size; } // or not.
      int len() const; // Calculate the size of current var (look for '\0').
      int len( const char* ) const; // Calculate the size of string provided (look for '\0').
      int allocated() const { return alloc_size; } // Return size set.
      var& flush(); // Flush the memory by freeing/deleting from memory.
      var& clean(); // Set item in array to '\0'.
      var& reSize( int stat_size = -1, bool stat = false, bool truncate = false ); // Resize array to desired size.
      friend int cmp( var & , const var &, bool exact = true ); // Compare var with var, mixed case match or not.
      friend int cmp( char* , const char* , bool exact = true ); 
      int cmp( const char* , bool exact = true ) const; // Compare with this object, mixed case match or not.
      friend int cmp( var & , const char, bool exact = true );
      int cmp( const char, bool exact = true ) const;
      var& cpy( const var & ); // Copy another object of class var to this object.
      var& cpy( const char*, const int );
      var& cpy( const char );
      friend var cpy( var & , const var & ); // Copy another object of class var to another object of the class var.
      friend var cpy( var & , const char );
      var& set( RXSTRING* & ); // Copy string in this object to a rexx string.
      var& get( const RXSTRING* ); // Copy rexx string to this object.
      var& cat( const var & ); // Concatenate (join) another class var with this object.
      var& revCat( const var & ); // Concatenate this object with another object of class var.
      friend var cat( var & , const var & ); // Concatenate (join) two classes var.
      var& cat( const char ); // Concatenate (join) a character with this object.
      friend var cat( var & , const char );
      var& cat( const int );
      friend var cat( var & , const int );
      var split( const int , int skip = 0 ); // Split this object and return rest, skip over number of characters.
      var split( const var & , bool skip = false ); // Find text and split this object and return rest.
      var split( const char, int start = 0, int n = 0 );
      friend var split( char* &, const int , int skip = 0 );
      var& remstr( const int , int n = 1 ); // Remove text from object, n number of characters.
      friend var remstr( var & , const int , int n = 1 );
      friend var remstr( char* , const int , int n = 1 );
      var& substr( int , int stop = -1, char pad = ' ' ); // Remove without, stop at end, pad if needed.
      var substr2( var & , int , int stop = -1, char pad = ' ' ) const; // Nondestructive version, returns copy.
      var substr2( int , int stop = -1, char pad = ' ' ) const;
      var substr2( const char* , int , int stop = -1, char pad = ' ' ) const;
      var& cal( const var& , Calc calc = Add ); // Calculate (if number found) and/or perform action specified.
      int boyerMooreSearch( const var & ) const; // Efficient algorithm to search for text with.
      friend int boyerMooreSearch( var & , const var & );
      int bruteForceSearch( const char , int start = 0, bool exact = true ) const; // Find character within object.
      friend int bruteForceSearch( var & , const char , int start = 0, bool exact = true );
      int reversebruteForceSearch( const char , int start = -1, bool exact = true ) const;
      friend int reversebruteForceSearch( var & , const char , int start = -1, bool exact = true );
      var& left( int pos ); // Keep text left of position in object.
      var& middle( int length ); // Keep text in middle with number of characters in object.
      var& right( int pos ); // Keep text right of position in object.
      var& right( const var & ); // Keep text right of text in class var in object.
      var right2( const var & ); // Nondestructive version, returns copy.
      var& leftOf( const var & ); // Keep text left of text in class var in object.
      var splitTo( const int , int skip = 0 ); // Keep text after position in object, return beginning.
      var splitTo( const var & , bool skip = false );
      var splitTo( const char, int start = 0, int n = 0 );
      var toLast2( const char ) const; // Nondestructive version, returns copy.
      var afterLast2( const char ) const; // Nondestructive version, returns copy.
      var& rightOf( const var & ); // Keep text right of text in class var in object.
      var& addRightOf( const var & ); // Reverse concatenation (join).
      int words( const char c = ' ' ) const; // Count number of words in object, specify delimiter.
      var word( int n, const char c = ' ' ) const; // return word delimited by character.
      var& removeText( const var & ); // Remove text from object.
      friend var& removeText( var & , const var & ); // Remove text from another object of class var.
      var& removeChar( const char ); // Remove first occurance of character from object.
      friend var& removeChar( var & , const char );
      var& removeByChar( const var & ); // Remove all occurances of character from object.
      var& translateChar( const char , const char ); // Replace character with another character in object.
      var& translateByChar( const var & , const var & ); // Replace all occurances of character in object.
      var& upper(); // Convert object to upper case.
      var& lower(); // Convert object to lower case.
      var& strip( const char c = ' ' ); // Strip object ends from character.
      var strip2( const char c = ' ' ) const; // Nondestructive version, returns copy.
      var& stripTrailing( const char c = ' ' ); // Strip object end from character.
      var stripTrailing2( const char c = ' ' ) const; // Nondestructive version, returns copy.
      var& insert( var &, int , bool truncate = true ); // Insert text into object.
      bool isDigit() const; // Indicate if object contain only number(s).
      bool isDigit( const char* ) const; // Indicate if string contain only number(s).
      bool isAlpha() const; //Indicate if object contain characters.
      bool isAlpha( const char* ) const; //Indicate if object contain characters.

/* Operations to perform on the class */
      friend ostream& operator << ( ostream& out, const var& v ); // cout etc.
      friend istream& operator >> ( istream& in, const var& v ); // cin etc.
      friend var operator + ( const char* , const var& ); // Join and calculate addition
      friend var operator + ( const char , const var& );
      friend var operator + ( const int , const var& );
      friend var operator + ( const long , const var& );
      friend var operator + ( const double , const var& );
      friend var operator - ( const char* , const var& ); // Remove and calculate subtraction
      friend var operator - ( const char , const var& );
      friend var operator - ( const int , const var& );
      friend var operator - ( const long , const var& );
      friend var operator - ( const double , const var& );
      friend var operator * ( const int , const var& ); // Multiply
      friend var operator * ( const long , const var& );
      friend var operator * ( const double , const var& );
      friend var operator / ( const char* , const var& ); // Split and calculate division
      friend var operator / ( const char , const var& );
      friend var operator / ( const int , const var& );
      friend var operator / ( const long , const var& );
      friend var operator / ( const double , const var& );
      operator char*() { return string; }; // Automatically pretend/appear as char* if needed.
      operator int() { return atoi( string ); }; // Automatically pretend/appear as int if needed.
      operator long() { return atol( string ); }; // Automatically pretend/appear as long if needed.
      operator double() { return atof( string ); }; // Automatically pretend/appear as double if needed.
      operator unsigned long() { return strtoul( string, NULL, 10 ); }; // Automatically appear as ulong if needed.
      operator bool() { return ( string[ 0 ] != '\0' ); }; // Automatically pretend/appear as bool if needed.
      var& operator = ( const char* ); // Copy.
      var& operator = ( const char );
      var& operator = ( const var& );
      var& operator = ( const int );
      var& operator = ( const long );
      var& operator = ( const double );
      bool operator < ( const char* ) const; // Smaller than (Comparison).
      bool operator < ( const char ) const;
      bool operator < ( const var& ) const;
      bool operator < ( const int ) const;
      bool operator < ( const long ) const;
      bool operator < ( const double ) const;
      bool operator > ( const char* ) const; // Larger than (Comparison).
      bool operator > ( const char ) const;
      bool operator > ( const var& ) const;
      bool operator > ( const int ) const;
      bool operator > ( const long ) const;
      bool operator > ( const double ) const;
      bool operator <= ( const char* ) const; // Smaller-Equal than (Comparison).
      bool operator <= ( const char ) const;
      bool operator <= ( const var& ) const;
      bool operator <= ( const int ) const;
      bool operator <= ( const long ) const;
      bool operator <= ( const double ) const;
      bool operator >= ( const char* ) const; // Larger-Equal than (Comparison).
      bool operator >= ( const char ) const;
      bool operator >= ( const var& ) const;
      bool operator >= ( const int ) const;
      bool operator >= ( const long ) const;
      bool operator >= ( const double ) const;
      bool operator == ( const char* ) const; // Equal to (Comparison).
      bool operator == ( const char ) const;
      bool operator == ( const var& ) const;
      bool operator == ( const int ) const;
      bool operator == ( const long ) const;
      bool operator == ( const double ) const;
      bool operator ^= ( const char* ) const; // Caseless (Comparison). (Nonstandard behaviour for ^=)
      bool operator ^= ( const char ) const;
      bool operator ^= ( const var& ) const;
      bool operator ^= ( const int ) const;
      bool operator ^= ( const long ) const;
      bool operator ^= ( const double ) const;
      bool operator != ( const char* ) const; // Not equal to (Comparison).
      bool operator != ( const char ) const;
      bool operator != ( const var& ) const;
      bool operator != ( const int ) const;
      bool operator != ( const long ) const;
      bool operator != ( const double ) const;
      var& operator += ( const char* ); // Add and summarize (Concatenation and calculation).
      var& operator += ( const char );
      var& operator += ( const var& );
      var& operator += ( const int );
      var& operator += ( const long );
      var& operator += ( const double );
      var& operator -= ( const char* ); // Remove and subtract from (Remove part of string and calculation).
      var& operator -= ( const char );
      var& operator -= ( const var& );
      var& operator -= ( const int );
      var& operator -= ( const long );
      var& operator -= ( const double );
      var& operator *= ( const int ); // Multiply with (Calculation).
      var& operator *= ( const long );
      var& operator *= ( const double );
      var& operator /= ( const char* ); // Split and devide (Split part of and calculation).
      var& operator /= ( const char );
      var& operator /= ( const var& );
      var& operator /= ( const int );
      var& operator /= ( const long );
      var& operator /= ( const double );
      var operator + ( const char* ) const; // Add and summarize (Concatenation and calculation).
      var operator + ( const char ) const;
      var operator + ( const var& ) const;
      var operator + ( const int ) const;
      var operator + ( const long ) const;
      var operator + ( const double ) const;
      var operator - ( const char* ) const; // Remove and subtract (Remove and calculation).
      var operator - ( const char ) const;
      var operator - ( const var& ) const;
      var operator - ( const int ) const;
      var operator - ( const long ) const;
      var operator - ( const double ) const;
      var operator * ( const int ) const; // Multiply (Calculation).
      var operator * ( const long ) const;
      var operator * ( const double ) const;
      var operator / ( const char* ) const; // Split and devide (Split and calculation).
      var operator / ( const char ) const;
      var operator / ( const var& ) const;
      var operator / ( const int ) const;
      var operator / ( const long ) const;
      var operator / ( const double ) const;
      char& operator [] ( const int ); // Access item in array specified by integer.
};
#endif