Ticket #245: var.hpp

File var.hpp, 50.1 KB (added by jep, 7 years ago)

String manipulation library

Line 
1/****************************************************************************
2*
3*  var.cpp
4*
5*  Create:  Dec 12 2004
6*  Update:  Sep 23 2005
7*  Rewrite:  Sep 07 2014
8*  © Jan-Erik Lärka 2004 - 2014, 2017
9*
10****************************************************************************/
11#pragma inline_depth 0;
12
13#ifndef VAR_HPP
14#define VAR_HPP
15
16#define __STDC_WANT_LIB_EXT1__ 1
17
18#ifndef TRUE
19  #define TRUE true
20#endif
21#ifndef FALSE
22  #define FALSE false
23#endif
24
25#ifdef __cplusplus
26  using namespace std;
27  #include <iostream>
28#else
29  #include <iostream.h>
30#endif
31
32#ifndef ULONG
33  #ifndef ULONG_TYPEDEFED
34    typedef unsigned long ULONG ;
35    #define ULONG_TYPEDEFED
36  #endif
37#endif
38
39#ifdef INCL_REXXSAA
40  #define INCL_REXXSAA
41  #include <rexxsaa.h>
42#endif
43#ifdef __REXXSAA_H_INCLUDED
44#define __REXXSAA_H_INCLUDED
45typedef struct RXSTRING_TYPE
46{
47    ULONG strlength ;
48    char* strptr ;
49} RXSTRING;
50typedef RXSTRING *PRXSTRING ;
51#endif
52
53typedef struct ints
54{
55    int val[8];
56    ints* ptr;
57} INTS;
58
59#include <stdlib.h>
60#include <stdio.h>
61#include <ctype.h>
62
63enum Calculate { Add, Sub, Mult, Div };
64enum Strip { Leading, Trailing, Both };
65enum Mode { Resize, Grow, Static, Reference };
66
67/* Methods (Member functions) for class */
68#define min(a,b)  (((a) < (b)) ? (a) : (b))
69#define max(a,b)  (((a) > (b)) ? (a) : (b))
70
71#ifdef __OS2__
72Mode osmode = Grow;
73#else
74Mode osmode = Resize;
75#endif
76
77class var {
78private:
79    char *string; //Pointer to array that hold the character string.
80    int alloc_size, alloc_mult; //Maintained value to indicate the length of the string.
81    Mode resizeable; //Maintained value to indicate how memory should be initialized.
82    ints *array, *e;
83
84    int intAt( int const start_pos ) {
85        return intAt( start_pos, NULL );
86    };
87
88    int intAt( int const start_pos, int value ) {
89        if( array == NULL ) {
90            array = new ints();
91            for( int j = 0; j < 8; j++ ) array->val[ j ] = -1;
92            array->ptr = NULL;
93        }
94        e = array;
95        for( int i = 0; i < start_pos / 8; i++ ) {
96            if( e->ptr == NULL ) {
97                e->ptr = new ints();
98                for( int j = 0; j < 8; j++ ) e->ptr->val[ j ] = -1;
99                e->ptr->ptr = NULL;
100            }
101            e = e->ptr;
102        }
103        if( value == NULL )
104            return e->val[ start_pos % 8 ];
105        else
106            return ( e->val[ start_pos % 8 ] = value );
107    };
108
109    bool init( int size_text, int reset_from = -1 ) {
110        alloc_size = 0;
111        size_text = size_text < 0 ? 0: size_text;
112        reset_from = reset_from < 0 ? size_text : reset_from;
113
114        if( resizeable == Reference ) return false;
115
116        int alloc = alloc_mult;
117        if( resizeable == Resize || string == NULL )
118            alloc = ( size_text / 8 + 1 ) * 8;
119        else if( resizeable == Grow )
120            alloc = max( alloc_mult, ( size_text / 8 + 1 ) * 8 );
121
122        if( string ) {
123            if( alloc != alloc_mult ) {
124                delete [] string;
125                string = new char[ alloc ];
126            }
127        } else
128            string = new char[ alloc ];
129        if( string ) {
130            for( int i = min( alloc - 1, reset_from ); i < alloc; i++ ) string[ i ] = '\0';
131            alloc_mult = alloc;
132            alloc_size = min( alloc, size_text );
133            return true;
134        } return false;
135    };
136
137public:
138    /* Constructor alt. 1
139     * var( size_t<, mode> )
140     *
141     * This constructor create the new object that can hold
142     * a string of specified size. Additionally it's possible
143     * to specify if the string/array should be static in size
144     * or dynamically resizeable by the class.
145     * Parameters:
146     *                size_text - number of characters (mandatory)
147     *                mode - how to allocate memory (mandatory)
148     */
149    var( int size_text, Mode mode ) : resizeable( mode ), string( NULL ), array( NULL ), e( NULL ) {
150        init( size_text, 0 );
151    };
152
153    /** Copy constructor
154     * var( class<<<,start_pos = 0> ,size_text = -1> , mode = Grow > )
155     *
156     * This copy constructor copy contence so it doesn't point to
157     * same address space. Additionally it's possible to specify
158     * if the target string/array should be dynamically resizeable.
159     * Parameters:
160     *                v - variable of class var with string (mandatory)
161     *                start_pos - start copying from (optional)
162     *                size_text - copy n characters. (optional)
163     *                mode - Grow by default on OS/2-eCS, follow length by default on Windows (optional)
164     */
165    var( var const &v, int start_pos = 0, int size_text = -1, Mode mode = osmode ) : resizeable( mode ), string( NULL ), array( NULL ), e( NULL ) {
166        cpy( v, start_pos, size_text );
167    };
168
169    /** Constructor alt. 2 (Default constructor too)
170     * var( <<<text>, size = -1>, static size = true> )
171     *
172     * This constructor create the new object that can hold
173     * a string of specified size. Additionally it's possible
174     * to specify if the string/array should be dynamically
175     * resizeable. If no parameters used it act as default
176     * constructor and just prepare for further use.
177     * Parameters:
178     *                text - string to set at creation (optional)
179     *                size_text - number of characters (optional)
180     *                mode - Grow by default on OS/2-eCS, follow length by default on Windows (optional)
181     */
182    var( const char *text = NULL, int size_text = -1, Mode mode = osmode ) : resizeable( mode ), string( NULL ), array( NULL ), e( NULL ) {
183        if ( size_text < 0 )
184            size_text = length( text );
185        if( init( size_text ) )
186            for( int i = 0; i < size_text && text[ i ]; i++ ) string[ i ] = text[ i ];
187    };
188
189    /** Constructor alt. 3
190     * var( text<, size_text = 1> )
191     *
192     * This constructor create the new object that can hold
193     * a string of specified size. Additionally it's possible
194     * to specify if the string/array should be dynamically
195     * resizeable.
196     * Parameters:
197     *                text - string to set at creation (mandatory)
198     *                size_text - number of characters (optional)
199     *                mode - Grow by default on OS/2-eCS, follow length by default on Windows (optional)
200     */
201    var( char text, int size_text = 1, Mode mode = osmode ) : resizeable( mode ), string( NULL ), array( NULL ), e( NULL ) {
202        if( init( text != '\0' ? size_text : 0 ) )
203            for( int i = 0; i < size_text; i++ ) string[ i ] = text;
204    };
205
206    /** Constructor alt. 4
207     * var( integer )
208     *
209     * This constructor create the new object that can hold
210     * a value originating from an integer.
211     * Parameters:
212     *                i - integer to convert to var (mandatory)
213     */
214    var( int i ) : resizeable( osmode ), string( NULL ), array( NULL ), e( NULL ) {
215        if( init( 17 ) )
216            itoa( i, string, 10 );
217        reSize( -1, resizeable );
218    };
219
220    /** Constructor alt. 5
221     * var( double )
222     *
223     * This constructor create the new object that can hold
224     * a value originating from a double.
225     * Parameters:
226     *                d - double to set at creation (mandatory)
227     *                mode - Grow by default on OS/2-eCS, follow length by default on Windows (optional)
228     */
229    var( double d, Mode mode = osmode ) : resizeable( mode ), string( NULL ), array( NULL ), e( NULL ) {
230        if( init( 35 ) )
231            gcvt( d, 10, string );
232        reSize( -1, resizeable );
233    };
234
235    /** Constructor alt. 6
236     * var( unsigned long )
237     *
238     * This constructor create the new object that can hold
239     * a value originating from an unsigned long.
240     * Parameters:
241     *                ul - unsigned long to set at creation (mandatory)
242     *                mode - Grow by default on OS/2-eCS, follow length by default on Windows (optional)
243     */
244    var( unsigned long ul, Mode mode = osmode ) : resizeable( mode ), string( NULL ), array( NULL ), e( NULL ) {
245        if( init( 17 ) )
246            ltoa( ul, string, 10 );
247        reSize( -1, resizeable );
248    };
249
250    /** Constructor alt. 7
251     * var( <text, size_text> )
252     *
253     * This constructor just reuse an already allocated string
254     * Parameters:
255     *                text - string to set at creation (required)
256     */
257    var( char *text, int size_text ) : resizeable( Reference ), array( NULL ), e( NULL ) {
258        if ( size_text < 0 )
259            alloc_size = length( text );
260        else
261            alloc_size = size_text;
262        alloc_mult = alloc_size;
263        string = text;
264    };
265
266    /** Destructor
267     * ~var()
268     *
269     * Destructor used to destroy allocated object and clean up memory.
270     * Parameters:
271     *                none
272     */
273    ~var() {
274        delete [] string;
275        while( e != NULL ) {
276            e = array->ptr;
277            delete array;
278            array = e;
279        }
280    };
281
282    //The following member functions are declared:
283    bool isNumeric() const { if( string[ 0 ] == '0' ) return TRUE; return atof( string ) != 0; };
284    bool isInteger() const { int i = atoi( string ); return ( ( i != 0 ) || ( string[ 0 ] == '0' && i == 0 ) ); };
285    bool isAlpha() const { if( alloc_size == 0 ) return false; double d = atof( string ); var temp( 35, Static ); gcvt( d, 10, temp ); return temp.length( false ) < alloc_size; }
286    bool isEmpty() const { return alloc_size == 0; };
287
288    var& reSize( int size_text = -1, Mode mode = osmode, bool truncate = true ) {
289
290        size_text = ( size_text < 0 ? length( false ) : size_text );
291        size_text = ( size_text < alloc_size ? ( truncate ? size_text : alloc_size ): size_text );
292        int alloc = alloc_mult;
293
294        if( resizeable == Resize || string == NULL )
295            alloc = ( size_text / 8 + 1 ) * 8;
296        else if( resizeable == Grow )
297            alloc = max( alloc_mult, ( size_text / 8 + 1 ) * 8 );
298
299        int i = 0;
300        if ( alloc_mult != alloc && resizeable != Static && resizeable != Reference ) { //Resize to
301            alloc_mult = alloc;
302            char* temp = new char[ alloc_mult ]; // Create a temporary string
303            if( temp != NULL ) {
304                for( ; i < min( alloc_size, size_text ); i++ ) temp[ i ] = string[ i ]; // Copy parts of string to temp storage
305                delete [] string; // Delete string
306                string = temp;
307            }
308        } else i = size_text;
309        alloc_size = size_text;
310        //for( ; i < alloc_mult; i++ )
311        string[ i ] = '\0';
312        resizeable = mode;
313        return ( *this );
314    };
315
316    var& flush() {
317        for( int i = alloc_size; i < alloc_mult; i++ ) string[ i ] = '\0';
318        return *this;
319    }
320
321    operator char const *() { return string; };
322    operator char *() { return string; };
323    operator char **() { return &string; };
324    operator unsigned char *() { return (unsigned char *) string; };
325    operator unsigned char **() { return (unsigned char **) string; };
326    operator char() const { return string[0]; };
327    operator int() { return atoi( string ); }; // Automatically pretend/appear as int if needed.
328    operator long() { return atol( string ); }; // Automatically pretend/appear as long if needed.
329    operator double() { return atof( string ); }; // Automatically pretend/appear as double if needed.
330    operator unsigned long() { return strtoul( string, NULL, 10 ); }; // Automatically appear as ulong if needed.
331
332    var &operator =( var const &v ) {
333        init( v.length() );
334        for( int i = 0; i < v.length(); i++ ) string[ i ] = v.string[ i ]; // Copy string
335        return ( *this );
336    };
337    var &operator =( char const *s ) {
338        int strlen = length( s );
339        init( strlen );
340        for( int i = 0; i < strlen; i++ ) string[ i ] = s[ i ]; // Copy string
341        return ( *this );
342    };
343    var &operator =( char const c ) {
344        if( init( 1 ) )
345            string[ 0 ] = c;
346        return ( *this );
347    };
348    var &operator =( int const i ) {
349        (*this) = fromInt( i );
350        return ( *this );
351    };
352    var &operator =( double const d ) {
353        (*this) = fromDouble( d );
354        return ( *this );
355    };
356    var &operator =( unsigned long const ul ) {
357        (*this) = fromULONG( ul );
358        return ( *this );
359    };
360
361    var &operator +=( var const &v ) {
362        calculate( v, Add );
363        return *this;
364    };
365    var &operator +=( char const *s ) {
366        calculate( s, Add );
367        return *this;
368    };
369    var &operator +=( char const c ) {
370        reSize( length() + 1, resizeable );
371        string[ length() + 1 ] = c;
372        return ( *this );
373    };
374    var &operator +=( int const i ) {
375        calculate( fromInt( i ), Add );
376        return ( *this );
377    };
378    var &operator +=( double const d ) {
379        calculate( fromDouble( d ), Add );
380        return ( *this );
381    };
382    var &operator +=( unsigned long const ul ) {
383        calculate( fromULONG( ul ), Add );
384        return ( *this );
385    };
386
387    var operator + ( char const *s ) const {
388        var retval( *this );
389        return retval += s;
390    };
391    var operator + ( char const c ) const {
392        var retval( *this );
393        return retval += c;
394    };
395    var operator + ( var const &v ) const {
396        var retval( *this );
397        return retval += v;
398    };
399    var operator + ( int const i ) const {
400        var retval( *this );
401        return retval += i;
402    };
403    var operator + ( double const d ) const {
404        var retval( *this );
405        return retval += d;
406    };
407    var operator + ( unsigned long const ul ) const {
408        var retval( *this );
409        return retval += ul;
410    };
411
412    var &operator -=( var const &v ) {
413        calculate( v, Sub );
414        return *this;
415    };
416    var &operator -=( char const *s ) {
417        calculate( s, Sub );
418        return *this;
419    };
420    var &operator -=( char const c ) {
421        remove( c );
422        return ( *this );
423    };
424    var &operator -=( int const i ) {
425        calculate( fromInt( i ), Sub );
426        return ( *this );
427    };
428    var &operator -=( double const d ) {
429        calculate( fromDouble( d ), Sub );
430        return ( *this );
431    };
432    var &operator -=( unsigned long const ul ) {
433        calculate( fromULONG( ul ), Sub );
434        return ( *this );
435    };
436
437    var operator - ( char const *s ) const {
438        var retval( *this );
439        return retval -= s;
440    };
441    var operator - ( char const c ) const {
442        var retval( *this );
443        return retval -= c;
444    };
445    var operator - ( var const &v ) const {
446        var retval( *this );
447        return retval -= v;
448    };
449    var operator - ( int const i ) const {
450        var retval( *this );
451        return retval -= i;
452    };
453    var operator - ( double const d ) const {
454        var retval( *this );
455        return retval -= d;
456    };
457    var operator - ( unsigned long const ul ) const {
458        var retval( *this );
459        return retval -= ul;
460    };
461
462    var &operator *=( var const &v ) {
463        calculate( v, Mult );
464        return *this;
465    };
466    var &operator *=( char const *s ) {
467        calculate( s, Mult );
468        return *this;
469    };
470
471    var &operator *=( int const i ) {
472        calculate( fromInt( i ), Mult );
473        return ( *this );
474    };
475    var &operator *=( double const d ) {
476        calculate( fromDouble( d ), Mult );
477        return ( *this );
478    };
479    var &operator *=( unsigned long const ul ) {
480        calculate( fromULONG( ul ), Mult );
481        return ( *this );
482    };
483
484    var operator * ( char const *s ) const {
485        var retval( *this );
486        return retval *= s;
487    };
488    var operator * ( char const c ) const {
489        var retval( *this );
490        return retval *= c;
491    };
492    var operator * ( var const &v ) const {
493        var retval( *this );
494        return retval *= v;
495    };
496    var operator * ( int const i ) const {
497        var retval( *this );
498        return retval *= i;
499    };
500    var operator * ( double const d ) const {
501        var retval( *this );
502        return retval *= d;
503    };
504    var operator * ( unsigned long const ul ) const {
505        var retval( *this );
506        return retval *= ul;
507    };
508
509    var operator /=( var const &v ) {
510        var retval( calculate( v, Div ) );
511        return retval;
512    };
513    var operator /=( char const *s ) {
514        var retval( calculate( s, Div ) );
515        return retval;
516    };
517    var operator /=( char const c ) {
518        int i = bruteForceSearch( c );
519        var retval;
520        if( i < 0 ) return retval;
521        retval = split( i, 1 );
522        return retval;
523    };
524    var operator /=( int const i ) {
525        var retval( calculate( fromInt( i ), Div ) );
526        return retval;
527    };
528    var operator /=( double const d ) {
529        var retval( calculate( fromDouble( d ), Div ) );
530        return retval;
531    };
532    var operator /=( unsigned long const ul ) {
533        var retval( calculate( fromULONG( ul ), Div ) );
534        return retval;
535    };
536
537    var operator / ( char const *s ) {
538        int i = boyerMooreSearch( s );
539        if( i > -1 )
540            return split( i, length( s ) );
541        return "";
542    };
543    var operator / ( char const c ) {
544        int i = bruteForceSearch( c );
545        if( i > -1 )
546            return split( i, 1 );
547        return "";
548    };
549    var operator / ( var const &v ) {
550        int i = boyerMooreSearch( v );
551        if( i > -1 )
552            return split( i, v.length() );
553        return "";
554    };
555    var operator / ( int const num ) {
556        var v( fromInt( num ) );
557        int i = boyerMooreSearch( v );
558        if( i > -1 )
559            return split( i, v.length() );
560        return "";
561    };
562    var operator / ( double const d ) {
563        var v( fromDouble( d ) );
564        int i = boyerMooreSearch( v );
565        if( i > -1 )
566            return split( i, v.length() );
567        return "";
568    };
569    var operator / ( unsigned long const ul ) {
570        var v( fromULONG( ul ) );
571        int i = boyerMooreSearch( v );
572        if( i > -1 )
573            return split( i, v.length() );
574        return "";
575    };
576
577    var &operator %=( var const &v ) {
578        split( v );
579        return *this;
580    };
581    var &operator %=( char const *s ) {
582        int i = reverseBoyerMooreSearch( s );
583        if( i > -1 )
584            split( i, length( s ) );
585        return *this;
586    };
587    var &operator %=( char const c ) {
588        int i = reverseBruteForceSearch( c );
589        if( i > -1 )
590            split( i, 1 );
591        return *this;
592    };
593    var &operator %=( int const i ) {
594        var retval( fromInt( i ) );
595        int num = reverseBoyerMooreSearch( retval );
596        if( num > -1 )
597            split( num, retval.length() );
598        return *this;
599    };
600    var &operator %=( double const d ) {
601        var retval( fromDouble( d ) );
602        int i = reverseBoyerMooreSearch( retval );
603        if( i > -1 )
604            split( i, retval.length() );
605        return *this;
606    };
607    var &operator %=( unsigned long const ul ) {
608        var retval( fromULONG( ul ) );
609        int i = reverseBoyerMooreSearch( retval );
610        if( i > -1 )
611            split( i, retval.length() );
612        return *this;
613    };
614
615    var operator % ( char const *s ) {
616        return split( s );
617    };
618    var operator % ( char const c ) {
619        return split( c );
620    };
621    var operator % ( var const &v ) {
622        return split( v );
623    };
624    var operator % ( int const i ) {
625        return split( fromInt( i ) );
626    };
627    var operator % ( double const d ) {
628        return split( fromDouble( d ) );
629    };
630    var operator % ( unsigned long const ul ) {
631       return split( fromULONG( ul ) );
632    };
633    var& operator ++ () {
634        return calculate( "1", Add );
635    };
636    var& operator ++ ( int ) {
637        return calculate( "1", Add );
638    };
639
640    var& operator -- () {
641        return calculate( "1", Sub );
642    };
643    var& operator -- ( int ){
644        return calculate( "1", Sub );
645    };
646
647/*    bool operator == ( char const *s ) const {
648        return ( match( s ) == 0 );
649    }
650
651    bool operator == ( char const c ) const {
652        return ( match( c ) == 0 );
653    }
654
655    bool operator == ( var const &v ) const {
656        return ( match( v ) == 0 );
657    }
658
659    bool operator == ( int const i ) const {
660        return ( match( fromInt( i ) ) == 0 );
661    }
662
663    bool operator == ( unsigned long const ul ) const {
664        return ( match( fromULONG( ul ) ) == 0 );
665    }
666
667    bool operator == ( double const d ) const {
668        return ( match( fromDouble( d ) ) == 0 );
669    }
670
671    bool operator != ( char const *s ) const {
672        return ( match( s ) != 0 );
673    }
674
675    bool operator != ( char const c ) const {
676        return ( match( c ) != 0 );
677    }
678
679    bool operator != ( var const &v ) const {
680        return ( match( v ) != 0 );
681    }
682
683    bool operator != ( int const i ) const {
684        return ( match( fromInt( i ) ) != 0 );
685    }
686
687    bool operator != ( unsigned long const ul ) const {
688        return ( match( fromULONG( ul ) ) != 0 );
689    }
690
691    bool operator != ( double const d ) const {
692        return ( match( fromDouble( d ) ) != 0 );
693    }*/
694
695
696    var operator ()( int const start_pos = 0, int const size_text = -1 ) const {
697        return cpy( start_pos, size_text );
698    };
699    char &operator ()( int const start_pos = 0 ) {
700        return string[ start_pos > 0 ? max( 0, start_pos ) % alloc_mult : 0 ];
701    };
702    char const &operator []( int const start_pos ) const {
703        return string[ alloc_size > 0 ? max( 0, start_pos ) % alloc_mult : 0 ];
704    };
705    char &operator []( int const start_pos ) {
706        return string[ alloc_size > 0 ? max( 0, start_pos ) % alloc_mult : 0 ];
707    };
708
709    int operator !() const { return ( alloc_size > 0 ); };
710    int length() const { return alloc_size; };
711    int length( bool allocated = true ) {
712        if( allocated ) return alloc_size;
713        alloc_size = 0;
714        const char *p = string;
715        while( *p && p != '\0' ) { p++; alloc_size++; }
716        return alloc_size; // Return number of characters
717
718    };
719    int length( char const *text ) {
720        int size = 0;
721        if( text ) {
722            const char *p = text;
723            while( *p && p != '\0' ) { p++; size++; }
724        }
725        return size; // Return number of characters
726    };
727    char const &get_at( int start_pos ) const {
728        return string[ alloc_size > 0 ? max( 0, start_pos ) % alloc_mult: 0 ];
729    };
730    void put_at( int start_pos, char c ) {
731        if( -1 < start_pos && start_pos < alloc_mult )
732            string[ max( 0, start_pos ) % alloc_mult ] = c;
733    };
734    int index( var const &v, int start_pos = -1 ) const { return boyerMooreSearch( v, start_pos ); };
735    var upper() const {
736        var retval( *this );
737        for( int i = 0; i < retval.length(); i++ ) retval.string[i] = toupper( retval.string[i] );
738        return retval;
739    };
740    var lower() const {
741        var retval( *this );
742        for( int i = 0; i < retval.length(); i++ ) retval.string[i] = tolower( retval.string[i] );
743        return retval;
744    };
745    int valid() const { return ( string != NULL ); };
746    int alloc_mult_size() const { return alloc_mult; };
747    int alloc_mult_size( int text_size ) { reSize( text_size, resizeable ); return alloc_mult; };
748
749    //The following friend functions are declared:
750
751    friend int   operator ==( var const &v1, var const &v2 ) { return v1.match( v2 ) == v1.length(); };
752    friend int   operator ==( var const &v,   char const *s ) { return v.match( s ) == v.length(); };
753    friend int   operator ==(   char const *s, var const &v ) { return v.match( s ) == v.length(); };
754    friend int   operator ==( var const &v,   char c        ) { return v.match( c ) == v.length(); };
755    friend int   operator ==(   char c      , var const &v ) { return v.match( c ) == v.length(); };
756    friend int   operator !=( var const &v1, var const &v2 ) { return v1.match( v2 ) < v1.length(); };
757    friend int   operator !=( var const &v,   char const *s ) { return v.match( s ) < v.length(); };
758    friend int   operator !=(   char const *s, var const &v ) { return v.match( s ) > v.length(); };
759    friend int   operator !=( var const &v,   char c        ) { return v.match( c ) < v.length(); };
760    friend int   operator !=(   char c      , var const &v ) { return v.match( c ) > v.length(); };
761    friend int   operator <( var const &v1, var const &v2 ) { return v1.match( v2 ) < 0; };
762    friend int   operator <( var const &v,   char const *s ) { return v.match( s ) < 0; };
763    friend int   operator <(   char const *s, var const &v ) { return v.match( s ) > 0; };
764    friend int   operator <( var const &v,   char c        ) { return v.match( c ) < 0; };
765    friend int   operator <(   char c      , var const &v ) { return v.match( c ) > 0; };
766    friend int   operator <=( var const &v1, var const &v2 ) { return v1.match( v2 ) <= v1.length(); };
767    friend int   operator <=( var const &v,   char const *s ) { return v.match( s ) <= v.length(); };
768    friend int   operator <=(   char const *s, var const &v ) { return v.match( s ) > v.length(); };
769    friend int   operator <=( var const &v,   char c        ) { return v.match( c ) <= v.length(); };
770    friend int   operator <=(   char c      , var const &v ) { return v.match( c ) > v.length(); };
771    friend int   operator >( var const &v1, var const &v2 ) { return v1.match( v2 ) > 0; };
772    friend int   operator >( var const &v,   char const *s ) { return v.match( s ) > 0; };
773    friend int   operator >(   char const *s, var const &v ) { return v.match( s ) < 0; };
774    friend int   operator >( var const &v,   char c        ) { return v.match( c ) > 0; };
775    friend int   operator >(   char c      , var const &v ) { return v.match( c ) < 0; };
776    friend int   operator >=( var const &v1, var const &v2 ) { return v1.match( v2 ) >= v1.length(); };
777    friend int   operator >=( var const &v,   char const *s ) { return v.match( s ) >= v.length(); };
778    friend int   operator >=(   char const *s, var const &v ) { return v.match( s ) < v.length(); };
779    friend int   operator >=( var const &v,   char c        ) { return v.match( c ) >= v.length(); };
780    friend int   operator >=(   char c      , var const &v ) { return v.match( c ) < v.length(); };
781
782/*    friend var operator +(       var &v1, var const &v2 ) {
783        var retval( v1 );
784        return retval += v2;
785    };
786    friend var operator +(       var &v,   char const *s ) {
787        var retval( v );
788        return retval += s;
789    };
790    friend var operator +(   char const *s, var const &v ) {
791        var retval( s );
792        return retval += v;
793    };*/
794    friend var operator +( int const , var const & );
795    //friend var operator +( unsigned long const , const var const & );
796    //friend var operator +( double const , const var const & );
797    friend int valid( var const &v ) { return ( v.string != NULL ); };
798
799    //The following I/O Stream inserter and extractor functions are declared:
800
801    friend istream &operator >>( istream &in, var &v ) { in >> v.string; return in; };
802    friend ostream &operator <<( ostream &out, var const &v ) { out << v.string; return out; };
803
804    var& calculate( var const &v, Calculate type, bool magic = false ) {
805        if( !isAlpha() || magic ) {
806            double this_num = atof( string ), v_num = atof( v.string );
807            var this_pre( 35, Grow ), v_pre( 35, Grow ), this_post( 35, Grow );
808            gcvt( this_num, 10, this_pre );
809            gcvt( v_num, 10, v_pre );
810            int v_len = v_pre.length( false );
811            switch( type ) {
812            case Sub:
813                this_num -= v_num;
814                break;
815            case Div:
816                if( v_num > 0 ) this_num /= v_num;
817                break;
818            case Mult:
819                this_num *= v_num;
820                break;
821            default:
822                this_num += v_num;
823            }
824            if( this_num > 0 && v_num > 0 ) {
825                gcvt( this_num, 10, this_post );
826                int this_pre_len = this_pre.length( false ), this_post_len = this_post.length( false );
827                this_post.reSize( this_post_len + length() - this_pre_len, resizeable );
828                for( int i = this_post_len, j = 0; j < min( this_post.alloc_size - this_pre_len, this_post.alloc_mult ); i++, j++ ) this_post[ i ] = string[ this_pre_len + j ]; // Copy parts of string to temp storage
829                reSize( this_post.length(), resizeable );
830                for( int i = 0; i < min( this_post.length(), alloc_size ); i++ ) string[ i ] = this_post[ i ]; // Copy to string
831                if( type == Add )
832                    merge( v( v_len ) );
833                else if( type == Sub )
834                    remove( v( v_len ) );
835                else if( type == Div )
836                    split( v( v_len ) );
837                else if( type == Mult )
838                    repeat( v( v_len ) );
839
840/*                int this_pre_len = length( this_pre ), this_post_length = this_post.reSize( -1, resizeable ).length();
841                int size_text = this_post_length + alloc_size - this_pre_len + v.length() - v_len;
842
843                if( resizeable == Grow )
844                    alloc_mult = max( alloc_mult, ( size_text / 8 + 1 ) * 8 );
845                else if( resizeable == Resize )
846                    alloc_mult = ( size_text / 8 + 1 ) * 8;
847
848                if ( size_text > alloc_mult )
849                    size_text = alloc_mult - 1;
850
851                char* temp = new char[ alloc_mult ]; // Create a temporary string
852                int i = 0, j;
853                if( temp != NULL ) {
854                    for( j = 0; j < this_post_length && i < min( size_text, alloc_mult ); i++, j++ ) temp[ i ] = this_post.string[ j ]; // Copy parts of string to temp storage
855                    for( j = 0; j < alloc_size - this_pre_len && i < min( size_text, alloc_mult ); i++, j++ ) temp[ i ] = string[ this_pre_len + j ]; // Copy parts of string to temp storage
856                    for( j = 0; j < v.length() - v_len && i < min( size_text, alloc_mult ); i++, j++ ) temp[ i ] = v.string[ v_len + j ]; // Copy parts of string to temp storage
857                    delete [] string; // Delete string
858                    string = temp;
859                    alloc_size = size_text;
860                }
861                for( int i = size_text; i < alloc_mult; i++ ) string[ i ] = '\0';*/
862            }
863        } else if( type == Add )
864            merge( v );
865        else if( type == Sub )
866            remove( v );
867        else if( type == Div )
868            split( v );
869        else if( type == Mult )
870            repeat( v );
871        return *this;
872    };
873
874    var fromInt( const int i ) const {
875        char retval[ 17 ];
876        itoa( i, retval, 10 );
877        return retval;
878    }
879    var fromULONG( const ULONG ul ) const {
880        char retval[ 17 ];
881        ltoa( ul, retval, 10 );
882        return retval;
883    }
884    var fromDouble( const double d ) const {
885        char retval[ 35 ];
886        gcvt( d, 10, retval );
887        return retval;
888    }
889#ifdef INCL_REXXSAA
890    var& set( RXSTRING &rxString ) {
891        if( rxString.strptr )
892            delete rxString.strptr;
893        rxString.strptr = new char[ alloc_size + 1 ];
894        if( rxString.strptr ) {
895            for( int i = 0; i <= alloc_size; i++ ) rxString.strptr[ i ] = string[ i ];
896            rxString.strlength = alloc_size;
897        } else {
898            rxString.strptr = 0;
899            rxString.strlength = 0;
900        }
901        return ( *this );
902    }
903    var& set( RXSTRING *rxString ) {
904        if( rxString->strptr )
905            delete rxString->strptr;
906        rxString->strptr = new char[ alloc_size + 1 ];
907        if( rxString->strptr ) {
908            for( int i = 0; i <= alloc_size; i++ ) rxString->strptr[ i ] = string[ i ];
909            rxString->strlength = alloc_size;
910        } else {
911            rxString->strptr = 0;
912            rxString->strlength = 0;
913        }
914        return ( *this );
915    }
916
917    var& flush( RXSTRING &rxString ) {
918        rxString.strptr = 0;
919        rxString.strlength = 0;
920        return ( *this );
921    }
922    var& get( PRXSTRING rxString ) {
923        if( rxString->strptr && rxString->strlength )
924            cpy( rxString->strptr, 0, rxString->strlength );
925        return ( *this );
926    }
927#endif
928
929    var &reverse() {
930        char temp;
931        char *pEnd, *pStart;
932
933        pEnd = string;
934        pStart = string;
935        while( *pEnd ) pEnd++;
936        while( pEnd > pStart ) {
937            pEnd--;
938            temp = *pEnd;
939            *pEnd = *pStart;
940            *pStart = temp;
941            pStart++;
942        }
943        return ( *this );
944    }
945
946    var &cat( const var &v1, const var &v2 = '\0', const var &v3 = '\0', const var &v4 = '\0', const var &v5 = '\0', const var &v6 = '\0', const var &v7 = '\0', const var &v8 = '\0', const var &v9 = '\0', const var &v10 = '\0', const var &v11 = '\0', const var &v12 = '\0' ) {
947        int i1 = v1.length(), i2 = v2.length(), i3 = v3.length();
948        int i4 = v4.length(), i5 = v5.length(), i6 = v6.length();
949        int i7 = v7.length(), i8 = v8.length(), i9 = v9.length();
950        int i10 = v10.length(), i11 = v11.length(), i12 = v12.length();
951        int i = length( false ), j;
952        reSize( i + i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9 + i10 + i11 + i12, resizeable );
953        for( j = 0; j < i1 && i < alloc_mult; string[ i++ ] = v1.string[ j++ ] );
954        for( j = 0; j < i2 && i < alloc_mult; string[ i++ ] = v2.string[ j++ ] );
955        for( j = 0; j < i3 && i < alloc_mult; string[ i++ ] = v3.string[ j++ ] );
956        for( j = 0; j < i4 && i < alloc_mult; string[ i++ ] = v4.string[ j++ ] );
957        for( j = 0; j < i5 && i < alloc_mult; string[ i++ ] = v5.string[ j++ ] );
958        for( j = 0; j < i6 && i < alloc_mult; string[ i++ ] = v6.string[ j++ ] );
959        for( j = 0; j < i7 && i < alloc_mult; string[ i++ ] = v7.string[ j++ ] );
960        for( j = 0; j < i8 && i < alloc_mult; string[ i++ ] = v8.string[ j++ ] );
961        for( j = 0; j < i9 && i < alloc_mult; string[ i++ ] = v9.string[ j++ ] );
962        for( j = 0; j < i10 && i < alloc_mult; string[ i++ ] = v10.string[ j++ ] );
963        for( j = 0; j < i11 && i < alloc_mult; string[ i++ ] = v11.string[ j++ ] );
964        for( j = 0; j < i12 && i < alloc_mult; string[ i++ ] = v12.string[ j++ ] );
965        return *this;
966    }
967
968    var split( int start_pos = 0, int skip = 0 ) { //Split and return string( s )
969        start_pos = min( max( 0, start_pos ), alloc_size );
970        skip = max( 0, skip );
971        var retval( alloc_size - start_pos - skip, resizeable );
972        for( int i = 0; i < retval.length(); i++ ) { retval.string[ i ] = string[ start_pos + skip + i ]; string[ start_pos + skip + i ] = '\0'; }
973        reSize( start_pos, resizeable );
974        return retval;
975    }
976
977    var split( const var& v ) { //Split and return string( s )
978        int i = boyerMooreSearch( v );
979        i = ( i > -1 ) ? i : v.length() - i;
980        return split( i, v.length() );
981    }
982
983    var split( const char c, int skip, bool exact ) {
984        int i = bruteForceSearch( c, -1, exact );
985        if ( i > -1 )
986            return split( i, abs( skip ) );
987        return "";
988    }
989
990    var remove( int start_pos, int len = 0 ) { // Return string
991        int i = 0;
992        int txtlen = min( alloc_size, abs( len ) + abs( start_pos ) );
993        var retval( txtlen, resizeable );
994        if( retval.string ) {
995            for( ; i < start_pos; i++ ) retval.string[ i ] = string[ i ];
996            for( ; i < txtlen; i++ ) retval.string[ i ] = string[ i + len ];
997        }
998        return retval;
999    }
1000
1001    var &remove( const char c ) { // Return string
1002        int i = bruteForceSearch( c );
1003        int j = i, k = 0;
1004        while ( i > -1 ) {
1005            for( ; j + k < i && j + k <= alloc_size; j++ ) string[ j ] = string[ j + k ];
1006            k++;
1007            i = bruteForceSearch( c, i + 1 );
1008        }
1009        for( ; j + k <= alloc_size; j++ ) string[ j ] = string[ j + k ];
1010        reSize( alloc_size - k + 1, resizeable );
1011        return *this;
1012    }
1013
1014    var &remove( const var& v ) { //Remove text
1015        return replace( v, "" );
1016    }
1017
1018    var &replace( const var& v, const var& v2 ) { // text
1019        int M = v.length();
1020        int newM = v2.length();
1021        int i = 0, j = 0, k = 0, l = 0,count = 0;
1022        int new_alloc_mult = alloc_mult, new_alloc_size = alloc_size;
1023        char* temp;
1024
1025        int skip[ 256 ];
1026        for ( i = 0; i < 256; ++i ) skip[ i ] = M;
1027        for ( i = 0; i < M; ++i ) skip[ v.string[ i ] ] = M - 1 - i;
1028
1029        i = M - 1;
1030        for( ; -2 < j && i < alloc_size; ) {
1031            for ( j = M - 1; 0 <= j; --i, --j )
1032                while ( string[ i ] != v.string[ j ] ) {
1033                    i += max( M - j, skip[ string[ i ] ] );
1034                    if( alloc_size <= i )
1035                    {
1036                        j = -2;
1037                        break;
1038                    }
1039                    j = M - 1;
1040                }
1041            if( -2 < j )
1042                i = intAt( count++, i + 1 ) + 1 + M;
1043        }
1044        if( newM - M != 0 && resizeable != Static && resizeable != Reference ) {
1045            new_alloc_size = alloc_size + count * ( newM - M );
1046            new_alloc_mult = ( new_alloc_size / 8 + 1 ) * 8;
1047            temp = new char[ new_alloc_mult ]; // Create a temporary string
1048        } else
1049            temp = string;
1050        if( temp != NULL && 0 < count ) {
1051            i = 0, j = 0, l = 0;
1052            for( ; i < count; i++ ) {
1053                for( ; l < intAt( i ); )
1054                    temp[ j++ ] = string[ l++ ];
1055                for( k = 0; k < newM; )
1056                    temp[ j++ ] = v2.string[ k++ ];
1057                l += M;
1058            }
1059            while( e != NULL ) {
1060                e = array->ptr;
1061                delete array;
1062                array = e;
1063            }
1064            if( newM - M != 0 ) {
1065                for( ; l < alloc_size; ) temp[ j++ ] = string[ l++ ];
1066                for( ; j < new_alloc_mult; ) temp[ j++ ] = '\0';
1067                if( resizeable != Static && resizeable != Reference ) {
1068                    delete [] string; // Delete string
1069                    string = temp;
1070                }
1071                alloc_size = new_alloc_size;
1072                alloc_mult = new_alloc_mult;
1073            }
1074        }
1075        return ( *this );
1076    }
1077
1078    var repeat( int count ) {
1079        var retval( *this );
1080        for( int i = 0; i < abs( count ); i++ )
1081            retval += (*this);
1082        return retval;
1083    }
1084
1085    var repeat( const var& v ) {
1086        var retval( *this );
1087        retval += v;
1088        return retval;
1089    }
1090
1091    int boyerMooreSearch( const var& needle, int start_pos = -1 ) const {
1092        int i, j;
1093        int skip[256];
1094        int M = needle.length();
1095
1096        for ( i = 0; i < 256; ++i ) skip[ i ] = M;
1097        for ( i = 0; i < M; ++i ) skip[ needle.string[ i ] ] = M - 1 - i;
1098
1099        start_pos = start_pos < 0 ? M : min( max( start_pos, M ), alloc_size ) - 1;
1100
1101        for ( i = start_pos, j = M - 1; j >= 0; --i, --j )
1102            while ( string[ i ] != needle.string[ j ] ) {
1103                i += max( M - j, skip[ string[ i ] ] );
1104                if ( i >= length() ) return -1;
1105                j = M - 1;
1106            }
1107        return i + 1;
1108    }
1109
1110    int reverseBoyerMooreSearch( const var& needle, int start_pos = -1 ) const {
1111        int i, j;
1112        int skip[256];
1113        int M = needle.length();
1114
1115        for ( i = 0; i < 256; ++i ) skip[ i ] = M;
1116        for ( i = 0; i < M; ++i ) skip[ needle.string[ i ] ] = M /*+ 1*/ - i;
1117
1118        start_pos = start_pos < 0 ? alloc_size - M : min( start_pos, alloc_size - M );
1119
1120        for ( i = start_pos, j = 0; j < M; ++i, ++j ) {
1121            while ( string[ i ] != needle.string[ j ] ) {
1122                i -= max( j, skip[ string[ i ] ] );
1123                if ( i < 0 ) return -1;
1124                j = 0;
1125            }
1126        }
1127        return i - M;
1128    }
1129
1130    var& strip( Strip type = Both, const char needle = ' ', bool exact = true ) {
1131        int fromStart = 0, fromEnd = alloc_size;
1132        if( type != Trailing )
1133            fromStart = max( 0, match( needle, exact ) );
1134        if( type != Leading )
1135            fromEnd = max( 0, match( needle, exact, true ) );
1136        fromEnd -= fromStart;
1137        if( fromStart > 0 )
1138            for( int i = 0; i < fromEnd; i++ ) string[ i ] = string[ i + fromStart ];
1139        if( fromEnd != alloc_size )
1140            reSize( fromEnd, resizeable );
1141        return (*this);
1142    }
1143
1144    int reverseBruteForceSearch( const char needle = ' ', int fromEnd = -1, bool caseSensetive = false ) const {
1145        int i = length() - ( fromEnd < 0 ? 0 : min( length(), fromEnd ) );
1146        if ( caseSensetive )
1147            for( i--; i > -1; i-- ) { if( string[ i ] == needle ) return i; }
1148        else
1149            for( i--; i > -1; i-- ) { if( toupper( string[ i ] ) == toupper( needle ) ) return i; }
1150        return -1;
1151    }
1152
1153    int bruteForceSearch( const char needle = ' ', int start = -1, bool caseSensetive = false ) const {
1154        int i = ( start < 0 ) ? 0 : min( start, length() ), stop = length();
1155        if ( caseSensetive )
1156            for( ; i < stop; i++ ) { if( string[ i ] == needle ) return i; }
1157        else
1158            for( ; i < stop; i++ ) { if( toupper( string[ i ] ) == toupper( needle ) ) return i; }
1159        return -1;
1160    }
1161
1162    int match( var const &v, bool caseSensetive = false ) const {
1163        double this_double = atof( string ), v_double = atof( v.string );
1164        if( this_double != 0 && v_double != 0 )
1165            return this_double < v_double;
1166        int i = 0, stop = min( alloc_size, v.length() );
1167        if ( caseSensetive )
1168            while( string[ i ] == v.string[ i ] && i < stop ) i++;
1169        else
1170            while( toupper( string[ i ] ) == toupper( v.string[ i ] ) && i < stop  ) i++;
1171        return ( ( ( int )( string[ i ] ) > ( int )( v.string[ i ] ) ) ? i : -i );
1172    }
1173
1174    int match( char const c, bool caseSensetive = false, bool reverse = false ) const {
1175        int pos = reverse ? alloc_size: 0;
1176        if( string ) {
1177            const char *p = string;
1178            if( caseSensetive ) {
1179                if( reverse )
1180                    while( *p && pos > -1 && ( string[ --pos ] != c || string[ pos ] == '\0' ) )
1181                        cout << string[ pos ];
1182                else
1183                    while( *p && string[ pos ] != c && string[ pos ] != '\0' ) { p++; pos++; }
1184            } else {
1185                char cup = toupper( c );
1186                if( reverse )
1187                    while( *p && pos > -1 && ( toupper( string[ --pos ] ) != cup || string[ pos ] == '\0' ) )
1188                        cout << string[ pos ];
1189                else
1190                    while( *p && toupper( string[ pos ] ) != cup && string[ pos ] != '\0' ) { p++; pos++; }
1191            }
1192        }
1193        return pos + reverse; // Return last pos of matching characters
1194    }
1195
1196    char* fromLast( var const c ) {
1197        return string + match( c, false, true );
1198    }
1199
1200    var &toLast( var const c ) {
1201        for( int i = match( c, false, true ); i < alloc_size; i++ ) string[ i ] = '\0';
1202        return *this;
1203    }
1204
1205    var &before( var const c, bool last = false ) {
1206        for( int i = match( c, false, last ) - 1; i < alloc_size; i++ ) string[ i ] = '\0';
1207        return *this;
1208    }
1209
1210    char* after( var const c, bool last = false ) {
1211        return string + match( c, false, last ) + 1;
1212    }
1213
1214    bool contains( const char* needle ) {
1215        const char* haystack = string;
1216        do {
1217            const char* h = haystack;
1218            const char* n = needle;
1219            while( toupper( (unsigned char) *h ) == toupper( (unsigned char) *n ) && *n ) {
1220                h++;
1221                n++;
1222            }
1223            if ( *n == 0 )
1224                return true;
1225        } while( *haystack++ );
1226        return false;
1227    }
1228
1229    bool wordBeginsWith( const var& needle, const var& delimiter = " ", bool caseSensetive = false ) const {
1230        int count = words( delimiter );
1231        for( int i = 0; i < count; i++ ) {
1232            if( subWord( 0, 1, delimiter ).beginsWith( needle, 0, caseSensetive ) ) return true;
1233        }
1234        return false;
1235    }
1236
1237    bool beginsWith( const var& needle, int start = 0, bool caseSensetive = false ) const {
1238        int strlen = length(), findlen = needle.length();
1239        int i = ( start < 0 ) ? 0 : min( start, strlen );
1240        for( ; i < strlen && i < findlen ; i++ ) {
1241            if( caseSensetive ) {
1242                if( string[ i ] != needle.string[ i ] ) goto done;
1243            } else {
1244                if( toupper( string[ i ] ) != toupper( needle[ i ] ) ) goto done;
1245            }
1246        }
1247    done:
1248        return ( i >= ( start + findlen ) );
1249    }
1250
1251    var subWord( int start_word = 0, int nr_words = -1, const var& delimiters = " " ) const { //Return part (word) of string
1252        int word, a, b, i = 0, j = 0, k = 0, strlen = length(), dellen = delimiters.length(), word_count = ( nr_words < 0 ) ? words( delimiters ) : abs( nr_words + start_word );
1253
1254        for( word = 0; word < start_word && i < strlen; word++ ) { // Word count
1255            for( i = k; i < strlen && j < dellen; i++ ) // Spaces
1256                for( j = 0; string[ i ] != delimiters.string[ j ] && j < dellen; j++ ); // Delimiters
1257            for( k = i + 1; k < strlen && j == dellen; k++ ) // Text to form Word
1258                for( j = 0; string[ k ] != delimiters.string[ j ] && j < dellen; j++ ); // Delimiters
1259        }
1260        for( a = b = k; word < word_count && a < strlen; word++ ) { // Word count
1261            for( a = b; a < strlen && j < dellen; a++ ) // Spaces
1262                for( j = 0; string[ a ] != delimiters.string[ j ] && j < dellen; j++ ); // Delimiters
1263            for( b = a + 1; b < strlen && j == dellen; b++ ) // Text to form Word
1264                for( j = 0; string[ b ] != delimiters.string[ j ] && j < dellen; j++ ); // Delimiters
1265        }
1266        return cpy( max( a - 1 , 0 ), max( ( b == 0 ) ? strlen : b - ( b < strlen ), 0 ) );
1267    }
1268
1269    int wordPos( const var &v, const var& delimiters = " ", bool caseSensetive = false ) const { //Return position of part (word) in string
1270        int word = 0, i = 0, j = 0, dellen = delimiters.length(), strlen = length(), vlen = v.length();
1271        for( ; i < strlen; word++ ) { // Word count
1272            for( j = 0; string[ i ] != delimiters.string[ 0 ] && i < strlen; ) {
1273                    if( caseSensetive ) {
1274                        for( int k = 0; string[ i++ ] == v.string[ k++ ] && i < strlen && k < vlen; )
1275                            if( k + 1 == vlen )
1276                                return word;
1277                    } else {
1278                        for( int k = 0; toupper( string[ i++ ] ) == toupper( v.string[ k++ ] ) && i < strlen && k < vlen; )
1279                            if( k + 1 == vlen )
1280                                return word;
1281                    }
1282            }
1283            for( j = 0; string[ i++ ] == delimiters.string[ j++ ] && i < strlen && j < dellen; ); // Delimiters
1284            if( j < dellen ) word--;
1285        }
1286        return word;
1287    }
1288
1289
1290    int wordPosIn( var &v, const var& delimiters = " ", bool caseSensetive = false ) const { //Return position of part (word) in string
1291        return v.wordPos( *this, delimiters, caseSensetive );
1292    }
1293
1294    int words( const char delimiter = ' ' ) const {
1295        int word = 0, i = 0, strlen = length();
1296        for( ; i < strlen; i++ ) {
1297            if( delimiter == string[ i ] ) word++;
1298        }
1299        if ( strlen > 0 )
1300            if( delimiter != string[ i - 1 ] ) word++;
1301        return word;
1302    }
1303
1304    int words( const var& delimiters ) const {
1305        int word = 0, i = 0, j = 0, dellen = delimiters.length(), strlen = length();
1306        for( ; i < strlen; word++ ) { // Word count
1307            for( ; i < strlen & j < dellen; i++ ) // Spaces
1308                for( j = 0; string[ i ] != delimiters.string[ j ] && j < dellen; j++ ); // Delimiters
1309            for( ; i < strlen & j == dellen; i++ ) // Text to form Word
1310                for( j = 0; string[ i ] != delimiters.string[ j ] && j < dellen; j++ ); // Delimiters
1311            if( j < dellen ) word--;
1312        }
1313        return word;
1314    }
1315
1316    var cpy( int start_pos = 0, int size_text = -1 ) const {
1317        start_pos = min( length(), max( 0, start_pos ) );
1318        size_text = size_text < 0 ? alloc_size - min( alloc_size, start_pos ) : size_text;
1319        var retval( size_text, resizeable );
1320        if( string != NULL )
1321            for( int i = 0; i < size_text; i++ ) retval.string[ i ] = string[ start_pos + i ];
1322        return retval;
1323    };
1324
1325    var &cpy( var const &v, int start_pos = 0, int size_text = -1 ) {
1326        int i, v_len = v.length();
1327        start_pos = min( v_len, max( 0, start_pos ) );
1328        if( size_text < 0 || v_len < size_text )
1329            size_text = v_len - start_pos;
1330        if( init( size_text, min( v_len, size_text ) ) )
1331            for( i = 0; i < min( v_len, size_text ); i++ ) string[ i ] = v[ start_pos + i ];
1332        return *this;
1333    };
1334
1335    var &merge( var const &v, int start_pos = 0, int size_text = -1 ) { //Join strings
1336        start_pos = ( start_pos < 0 ) ? 0 : start_pos;
1337        int strlen = ( ( size_text < 0 ) ? v.length() : size_text ) - start_pos, alloc = alloc_size;
1338        reSize( alloc + strlen, resizeable );
1339        if( string ) {
1340            for( int i = 0; i < strlen; i++ )
1341                string[ alloc + i ] = v.string[ start_pos + i ];
1342            alloc_size = alloc + strlen;
1343        }
1344        return *this;
1345    };
1346
1347    var &left( int text_size = -1 ) {
1348        var temp;
1349        return temp.cpy( *this, 0, text_size < 0 ? alloc_size : text_size );
1350    }
1351
1352    var &right( int text_size = 0 ) {
1353        var temp;
1354        return temp.cpy( *this, text_size, alloc_size );
1355    }
1356};
1357#endif