Ticket #245: var.hpp

File var.hpp, 50.1 KB (added by jep, 8 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