home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #18 / NN_1992_18.iso / spool / comp / lang / cplus / 12602 < prev    next >
Encoding:
Text File  |  1992-08-19  |  67.7 KB  |  2,686 lines

  1. Newsgroups: comp.lang.c++
  2. Path: sparky!uunet!stanford.edu!ames!pacbell.com!tlhouns
  3. From: tlhouns@srv.PacBell.COM (Lee Hounshell)
  4. Subject: VAR - a string class library (source)
  5. Message-ID: <1992Aug20.012612.18347@PacBell.COM>
  6. Sender: news@PacBell.COM (Pacific Bell Netnews)
  7. Organization: Pacific * Bell
  8. Date: Thu, 20 Aug 1992 01:26:12 GMT
  9. Lines: 2675
  10.  
  11.  
  12. This is "var", a C++ object library that is kinda like a "super-string" class.
  13. The var class does a pretty good job of offering a data object that assumes
  14. its "type" at run time, based on context of use.  Rarely will you need to
  15. declare int's, or longs, or doubles or char[] or even string objects again!
  16. "Var" does it all (or at least tries to).
  17.  
  18.     + var will do base data types (eg: int, long, char *, float, string ...)
  19.     + var will do arithmetic
  20.     + var will do strings and operations on strings
  21.     + var will do sub-strings and operations on sub-strings
  22.     + var will intelligently "mix" operations between mixed types
  23.     + var will do formatted output using the stream library
  24.     + individual vars can be "staticly" typed, or they can assume
  25.       type at runtime, based on context.
  26.  
  27. To use this class, simply type make and a library file "libvar.a" will be
  28. created.  This class has been used extensively here at Pacific Bell as a
  29. base class in development of our own internal C++ class libraries. I've
  30. even used "var" as the YYSTYPE type inside yacc/lex programs!!
  31.  
  32. If there is sufficient interest in "var" I may post a few other "base" C++
  33. classes that I've developed.. such as an "associative array" class that uses
  34. a "var" to index another "var."
  35.  
  36. If you like (or dislike) var, please drop me a line.
  37. Mail bug reports and comments to:
  38. tlhouns@srv.pacbell.com
  39.  
  40. enjoy.
  41.  
  42. -Lee
  43.  
  44.  
  45.  
  46. #-----------------------------------cut here----------------------------------
  47.  
  48. # This is a shell archive.  Remove anything before this line,
  49. # then unpack it by saving it in a file and typing "sh file".
  50. #
  51. # Wrapped by photon!tlhouns on Wed Aug 19 18:18:18 PDT 1992
  52. # Contents:  README LEGAL_NOTICE var.3++ Makefile var.H var.C Misc.H Misc.C
  53. #    demo.C
  54.  
  55. echo x - README
  56. sed 's/^@//' > "README" <<'@//E*O*F README//'
  57.  
  58. This is "var", a C++ object library that is kinda like a "super-string" class.
  59. The var class does a pretty good job of offering a data object that assumes
  60. its "type" at run time, based on context of use.  Rarely will you need to
  61. declare int's, or longs, or doubles or char[] or even string objects!
  62. "Var" does it all (or at least tries to).
  63.  
  64.     + var will do base data types (eg: int, long, char *, float, string ...)
  65.     + var will do arithmetic
  66.     + var will do strings and operations on strings
  67.     + var will do sub-strings and operations on sub-strings
  68.     + var will intelligently "mix" operations between mixed types
  69.     + var will do formatted output using the stream library
  70.     + individual vars can be "staticly" typed, or they can assume
  71.       type at runtime, based on context.
  72.  
  73. To use this class, simply type make and a library file "libvar.a" will be
  74. created.  This class has been used extensively here at Pacific Bell as a
  75. base class in development of our own internal C++ class libraries. I've
  76. even used "var" as the YYSTYPE type inside yacc/lex programs!!
  77.  
  78. If there is sufficient interest in "var" I may post a few other "base" C++
  79. classes that I've developed.. such as an "associative array" class that uses
  80. a "var" to index another "var."
  81.  
  82. If you like (or dislike) var, please drop me a line.
  83. Mail bug reports and comments to:
  84. tlhouns@srv.pacbell.com
  85.  
  86. -Lee
  87. @//E*O*F README//
  88. chmod u=rw,g=r,o=r README
  89.  
  90. echo x - LEGAL_NOTICE
  91. sed 's/^@//' > "LEGAL_NOTICE" <<'@//E*O*F LEGAL_NOTICE//'
  92.  
  93.         Any use of this source code must include, in the user documentation
  94.         and internal comments to the code, and notices to the end user as
  95.         follows:
  96.  
  97.     Copyright (c) 1992 Lee Hounshell
  98.  
  99.     LEE HOUNSHELL MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF
  100.         THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS"
  101.         WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  LEE HOUNSHELL
  102.     SEVERALLY AND INDIVIDUALLY, DISCLAIM ALL WARRANTIES WITH REGARD
  103.     TO THIS SOURCE CODE, INCLUDING ALL IMPLIED WARRANTIES OF
  104.     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO
  105.     EVENT SHALL LEE HOUNSHELL BE LIABLE FOR ANY SPECIAL, INDIRECT,
  106.     INCIDENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
  107.     RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  108.     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  109.     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.
  110.  
  111.     Permission to use, copy, modify, and distribute this software
  112.     and its documentation for any purpose and without fee is hereby
  113.     granted, provided that the above copyright notice appear in all
  114.     copies and that both that copyright notice and this permission
  115.     notice appear in supporting documentation, and that the name of
  116.     Lee Hounshell not be used in advertising in publicity pertaining
  117.     to distribution of the software without specific, written prior
  118.     permission.
  119.  
  120. @//E*O*F LEGAL_NOTICE//
  121. chmod u=rw,g=r,o=r LEGAL_NOTICE
  122.  
  123. echo x - var.3++
  124. sed 's/^@//' > "var.3++" <<'@//E*O*F var.3++//'
  125. @.po 6
  126. @.TH VAR 3++ "1/92" "Version 1.0" "Variable Base Type String Class Library"
  127.  
  128. @.SH CLASS
  129. VAR    \- Variable Base Type String Class Library
  130. @.SH SYNOPSIS
  131. @.B #include     <var.H>
  132. @.PP
  133. @.nf
  134. @.ta.5i 1.0i 4.0i
  135. \fB
  136. class var {
  137.  
  138.   public:
  139.     // Constructors & Destructors
  140.     var(void);                    // constructor
  141.     var(const varsize &);            // constructor
  142.     var(const char *);                // constructor
  143.     var(const char);                // constructor
  144.     var(const short);                // constructor
  145.     var(const unsigned short);            // constructor
  146.     var(const int);                // constructor
  147.     var(const unsigned int);            // constructor
  148.     var(const long);                // constructor
  149.     var(const unsigned long);            // constructor
  150.     var(const double);                // constructor
  151.     var(const var &);                // copy constructor
  152.     ~var(void);                    // destructor
  153.  
  154.     // Operators
  155.     var & operator = (const char *);        // assignment
  156.     var & operator = (const var &);        // assignment
  157.     char & operator [] (const int);        // indexing
  158.     subvar & operator () (int, int) const;    // substring
  159.     subvar & operator () (const int) const;    // substring
  160.     friend ostream & operator << (ostream &, const var &); // output
  161.     friend istream & operator >> (istream &, var &); // input
  162.     friend class subvar;            // substring
  163.  
  164.     // More Operators (used for arithmetic type extension)
  165.     var & operator = (const char);        // assignment
  166.     var & operator = (const short);        // assignment
  167.     var & operator = (const unsigned short);    // assignment
  168.     var & operator = (const int);        // assignment
  169.     var & operator = (const unsigned int);    // assignment
  170.     var & operator = (const long);        // assignment
  171.     var & operator = (const unsigned long);    // assignment
  172.     var & operator = (const double);        // assignment
  173.  
  174.     // Casting Operators
  175.     operator char * (void) const;        // type conversion
  176.     operator double (void) const;        // type conversion
  177.  
  178.     // Assignment Operators
  179.     var & operator ++ (void);            // increment (pre-index only)
  180.     var & operator -- (void);            // decrement (pre-index only)
  181.     var operator ! (void) const;        // not
  182.  
  183.     var operator + (const var &) const;        // addition OR concatenation
  184.     var operator - (const var &) const;        // subtraction
  185.     var operator * (const var &) const;        // multiplication
  186.     var operator / (const var &) const;        // division
  187.     var operator % (const var &) const;        // remainder
  188.  
  189.     var & operator += (const var &);        // addition OR concatenation
  190.     var & operator -= (const var &);        // subtraction
  191.     var & operator *= (const var &);        // multiplication
  192.     var & operator /= (const var &);        // division
  193.     var & operator %= (const var &);        // remainder
  194.  
  195.     var & operator += (const char &);        // addition OR concatenation
  196.     var & operator += (const char *);        // addition OR concatenation
  197.     var & operator -= (const char *);        // subtraction
  198.     var & operator *= (const char *);        // multiplication
  199.     var & operator /= (const char *);        // division
  200.     var & operator %= (const char *);        // remainder
  201.  
  202.     var & operator += (const double);        // addition OR concatenation
  203.     var & operator -= (const double);        // subtraction
  204.     var & operator *= (const double);        // multiplication
  205.     var & operator /= (const double);        // division
  206.     var & operator %= (const double);        // remainder
  207.  
  208.     friend var operator + (const char *, const var &); // addition OR concatenation
  209.     friend var operator - (const char *, const var &); // subtraction
  210.     friend var operator * (const char *, const var &); // multiplication
  211.     friend var operator / (const char *, const var &); // division
  212.     friend var operator % (const char *, const var &); // remainder
  213.     friend var operator + (const var &, const char *); // addition OR concatenation
  214.     friend var operator - (const var &, const char *); // subtraction
  215.     friend var operator * (const var &, const char *); // multiplication
  216.     friend var operator / (const var &, const char *); // division
  217.     friend var operator % (const var &, const char *); // remainder
  218.  
  219.     friend var operator + (const var &, const double); // addition OR concatenation
  220.     friend var operator - (const var &, const double); // subtraction
  221.     friend var operator * (const var &, const double); // multiplication
  222.     friend var operator / (const var &, const double); // division
  223.     friend var operator % (const var &, const double); // remainder
  224.     friend var operator + (const double, const var &); // addition OR concatenation
  225.     friend var operator - (const double, const var &); // subtraction
  226.     friend var operator * (const double, const var &); // multiplication
  227.     friend var operator / (const double, const var &); // division
  228.     friend var operator % (const double, const var &); // remainder
  229.  
  230.     // Equality Operators
  231.     int operator == (const var &) const;    // equality
  232.     int operator != (const var &) const;    // inequality
  233.     int operator < (const var &) const;        // less than
  234.     int operator > (const var &) const;        // greater than
  235.     int operator <= (const var &) const;    // less than or equal
  236.     int operator >= (const var &) const;    // greater than or equal
  237.  
  238.     friend int operator == (const var &, const char *); // equality
  239.     friend int operator != (const var &, const char *); // inequality
  240.     friend int operator < (const var &, const char *);  // less than
  241.     friend int operator > (const var &, const char *);  // greater than
  242.     friend int operator <= (const var &, const char *); // less than or equal
  243.     friend int operator >= (const var &, const char *); // greater than or equal
  244.     friend int operator == (const char *, const var &); // equality
  245.     friend int operator != (const char *, const var &); // inequality
  246.     friend int operator < (const char *, const var &);  // less than
  247.     friend int operator > (const char *, const var &);  // greater than
  248.     friend int operator <= (const char *, const var &); // less than or equal
  249.     friend int operator >= (const char *, const var &); // greater than or equal
  250.  
  251.     friend int operator == (const var &, const double); // equality
  252.     friend int operator != (const var &, const double); // inequality
  253.     friend int operator < (const var &, const double);  // less than
  254.     friend int operator > (const var &, const double);  // greater than
  255.     friend int operator <= (const var &, const double); // less than or equal
  256.     friend int operator >= (const var &, const double); // greater than or equal
  257.     friend int operator == (const double, const var &); // equality
  258.     friend int operator != (const double, const var &); // inequality
  259.     friend int operator < (const double, const var &);  // less than
  260.     friend int operator > (const double, const var &);  // greater than
  261.     friend int operator <= (const double, const var &); // less than or equal
  262.     friend int operator >= (const double, const var &); // greater than or equal
  263.  
  264.     // Custom Interface
  265.     void null(int);                // "null" out string
  266.     void changesize(int);            // change allocated memory
  267.     int length(void) const;            // length of string
  268.     const char * vartype(void) const;        // name of this var type
  269.     void change_type(const char *);        // change var type
  270.     int is_string(void) const;            // test var type
  271.     int is_double(void) const;            // test var type
  272.     int is_long(void) const;            // test var type
  273.     int strchr(const char) const;        // strchr(char) index
  274.     int strrchr(const char) const;        // strrchr(char) index
  275.     var & concat(const var &);            // concatenation
  276.     var & format(const char *);            // set output format
  277. };
  278. @.fi
  279. \fP
  280.  
  281. @.SH DESCRIPTION
  282. Class \fBvar\fP represents a \fBstring\fP object class that also provides all
  283. the traditional functionality of the C base types: char, int, long, float, double, and char*.
  284. \fBVar\fP, is in many ways a "super-string" class.
  285. The var class does a pretty good job of offering a base data "container" object that can either
  286. assume its "type" at run time, based on context or remain a "fixed" type, always.
  287.  
  288. @.SS var will do
  289. @.TP 2
  290. +
  291. all the base data types (eg: short, int, long, char *, float, double ...)
  292. @.TP 2
  293. +
  294. string types
  295. @.TP 2
  296. +
  297. arithmetic
  298. @.TP 2
  299. +
  300. strings and operations on strings
  301. @.TP 2
  302. +
  303. sub-strings and operations on sub-strings
  304. @.TP 2
  305. +
  306. intelligent "mixing" of operations between mixed types
  307. @.TP 2
  308. +
  309. formatted output using the stream library
  310.  
  311. @.SH PUBLIC CONSTRUCTORS
  312. @.SS var(void);
  313. This constructor is used to declare an "untyped" var object.  Type is determined
  314. at run-time, based on context of use.
  315.  
  316. @.SS var(const varsize &);
  317. This constructor is used to declare an "string" var object, with preallocated memory.
  318. The object's type can change at run-time, based on context.
  319.  
  320. @.SS var(const char *);
  321. This constructor is used to declare a "string" object initialize from a "char *".
  322. The object's type can change at run-time, based on context.
  323.  
  324. @.SS var(const char);
  325. This constructor is used to declare an "numeric" var object, initialized from a char.
  326. The object's type can change at run-time, based on context.
  327.  
  328. @.SS var(const short);
  329. This constructor is used to declare an "numeric" var object, initialized from a short.
  330. The object's type is fixed and will not change at run-time.
  331.  
  332. @.SS var(const unsigned short);
  333. This constructor is used to declare an "numeric" var object, initialized from an unsigned short.
  334. The object's type is fixed and will not change at run-time.
  335.  
  336. @.SS var(const int);
  337. This constructor is used to declare an "numeric" var object, initialized from an int.
  338. The object's type is fixed and will not change at run-time.
  339.  
  340. @.SS var(const unsigned int);
  341. This constructor is used to declare an "numeric" var object, initialized from an unsigned int.
  342. The object's type is fixed and will not change at run-time.
  343.  
  344. @.SS var(const long);
  345. This constructor is used to declare an "numeric" var object, initialized from a long.
  346. The object's type is fixed and will not change at run-time.
  347.  
  348. @.SS var(const unsigned long);
  349. This constructor is used to declare an "numeric" var object, initialized from an unsigned long.
  350. The object's type is fixed and will not change at run-time.
  351.  
  352. @.SS var(const double);
  353. This constructor is used to declare an "numeric" var object, initialized from a double or float.
  354. The object's type is fixed and will not change at run-time.
  355.  
  356. @.SS var(const var &);
  357. This constructor is used to declare a var object, which is a copy of another var.
  358. The object assumes the characteristics of the initializing object.
  359.  
  360. @.SS ~var(void);
  361. The destructor returns all memory allocated by the object back to the OS.
  362.  
  363.  
  364. @.SH PUBLIC OPERATORS
  365. @.SS Arithmetic and Concatenation Operators
  366. Most operators (+, -, /, *, %, +=, etc..) will operate as expected.
  367. The "+" and "+=" operators will either do addition or concatenation, as appropriate.
  368. if concatenation is required, then the \fB"var.concat(var)"\fP member function should
  369. be used.
  370.  
  371. @.SS Relational Operators
  372. These also operate as expected.  If "string" objects are compared, the comparison
  373. will be as performed by \fBstrcmp(3)\fP.
  374.  
  375. @.SS The Indexing Operator []
  376. You can index a character from inside a \fBvar\fP by using
  377. the \fB"char & operator [] (const int);"\fP operator.
  378. A reference to the character is returned, which can be assigned to.
  379. Do not assign the NULL character using this operator.
  380. Instead call the member function \fB"null(index)"\fP.
  381.  
  382. @.SS Sub-strings
  383. Two operators are provide for substring operation.  The
  384. first, \fB"subvar & operator () (int start, int length) const;"\fP
  385. will extract a string starting at "start" for "length" characters.
  386. The second, \fB"subvar & operator () (const int start) const;"\fP will
  387. extract a string starting at "start" to the end of the string.
  388.  
  389. @.SS Type Casting
  390. Only two type casts are required by \fBvar\fP. The first converts
  391. the object into a "char *".  The second converts the object into a
  392. double.  Implicit conversion between "char *" and "double" types
  393. will be performed by your C++ compiler.
  394.  
  395. @.SS Formatted Input/Output
  396. You can usr \fBvar\fP with the io stream library.  Object can be
  397. both output and input using the ">>" and "<<" operators.
  398. For formatted output, be sure to set the object's "format template"
  399. prior to calling the ">>" operator.  (see \fB"var & format(const char *);"\fP)
  400.  
  401. @.SH PUBLIC MEMBER FUNCTIONS
  402.  
  403. @.SS Truncating a string 
  404. The \fB"void null(int index);"\fP function will truncate a \fBvar\fP
  405. object, starting from the specified index postion.
  406.  
  407. @.SS Memory Allocation
  408. The \fB"void changesize(int newsize);"\fP can be used to increase
  409. allocated memory for a var.  Memory can NOT be decreased.  Allocated
  410. memory is returned to the heap when an object goes out of scope.
  411.  
  412. @.SS Determining Var's Length
  413. The \fB"int length(void) const;"\fP function returns the "size" of a \fBvar\fP.
  414.  
  415. @.SS Determining Var's Type
  416. The \fB"const char * vartype(void) const;"\fP function returns the "type" of a \fBvar\fP.
  417. Possible types are: "VAR_STRING", "VAR_LONG" and "VAR_DOUBLE".
  418.  
  419. @.SS Explititly Changing a Var's Type
  420. The \fB"void change_type(const char *newtype);"\fP function can be used
  421. to set an exact type.  Valid values for "newtype" are "string", "short",
  422. "unsigned short", "int", "unsigned int", "long", "unsigned long",
  423. "float", and "double".
  424.  
  425. @.SS Testing a Var's Type
  426. Three functions are provided that allow testing a \fBvar\fP type.
  427. They are as follows: \fB"int is_string(void) const;"\fP,
  428. \fB"int is_double(void) const;"\fP, and \fB"int is_long(void) const;"\fP
  429.  
  430. @.SS Searching for a Character
  431. Two functions are provided that search a \fBvar\fP for a specified
  432. character.  Both return an offset.  The first \fB"int strchr(const char) const;"\fP
  433. searches forward.  The second, \fB"int strrchr(const char) const;"\fP
  434. searches backward.
  435.  
  436. @.SS Concatenation
  437. Concatenation can be forced, regardless of type with the \fB"var & concat(const var &);"\fP
  438. function.
  439.  
  440. @.SS Setting the Output Format
  441. The \fB"var & format(const char *fmt);"\fP function will allow you to specify an
  442. output format.  This format will remain in effect until changed.  Printf()
  443. style output formats can be introduced anywhere in the format statment.
  444. Multiple formateed output directives can appear in the same "fmt".  Each
  445. directive will receive a copy of the object.  Automatic type conversion will
  446. occur.
  447.  
  448.  
  449. @.SH AUTHOR
  450. Lee Hounshell - 1/92
  451.  
  452. @.SH EXAMPLE
  453. @.nf
  454. #include    <stdlib.h>
  455. #include    <stream.h>
  456. #include    <var.H>
  457.  
  458. main ()
  459. {
  460.     var value;                // declare an "untyped" var
  461.     value = "hello world";        // initialize it
  462.     cout << value << endl;        // output "hello world"
  463.     value = value(3, value.length() - 6); // substring example
  464.     cout << value << endl;        // output "lo wo"
  465.     value = 35;                // assignment of int
  466.     value += 42.375;            // add 42.375 to present value
  467.     cout << value << endl;        // output "77.375"
  468.     cout << value.format("formatted output example %05d of value") << endl;
  469.     cout << value.format("multiple outputs #1=%d, #2=%9.2f of value") << endl;
  470.     value.null(2);            // truncate string
  471.     value += " sunset strip";        // concatenate a string
  472.     cout << value.format("%s") << endl;    // output "77 sunset strip"
  473.     cout << value[3] << value[4] << value[5] << endl; // output "sun"
  474. }
  475. @.fi
  476.  
  477. @.SH SUPERCLASSES
  478. none.
  479.  
  480. @.SH SUBCLASSES
  481. none
  482.  
  483. @.SH BUGS
  484. Assignment of an array of vars to another array of vars
  485. must currently be done one elemnt at a time.
  486.  
  487. @//E*O*F var.3++//
  488. chmod u=rw,g=r,o=r var.3++
  489.  
  490. echo x - Makefile
  491. sed 's/^@//' > "Makefile" <<'@//E*O*F Makefile//'
  492. ############################################################################
  493. #       make - compiles the C++ library (libvar.a) 
  494. #       make clean - removes all .o files generated in these procedures
  495. #       make clobber - removes all libraries, cleans up .o's
  496. ############################################################################
  497.  
  498.  
  499. # from the two below, pick the operating system closest to yours:
  500. INCDIRS = -I.
  501.  
  502. SYS    = SUN
  503. CC    = CC
  504. CFLAGS    = -O $(INCDIRS)
  505. ARFLAGS    = rv
  506.  
  507.  
  508. is_bsd    = test $(SYS) = SUN
  509.  
  510. all:    libvar.a
  511.  
  512. C++FILES = var.C Misc.C
  513. INS_HFILES = var.H Misc.H
  514. HFILES   =    $(INS_HFILES)
  515.  
  516. OBJECTS = ${C++FILES:.C=.o}
  517.  
  518. libvar.a:    $(OBJECTS)
  519.         ar $(ARFLAGS) $@ $?
  520.         if $(is_bsd) ; then ranlib $@; fi
  521.  
  522. $(OBJECTS):    $(HFILES)
  523.     
  524.  
  525. clean:    
  526.         rm -f *.o a.out core $(OBJECTS)
  527.         cd demo; $(MAKE) clean
  528.  
  529. clobber:    clean
  530.         rm -fr $(DOTAS)
  531.         cd demo; $(MAKE) clobber
  532.  
  533. #####
  534. #####
  535. #.SUFFIXES: .o .C .C~ .c .c~
  536. @.SUFFIXES: .o .C .C~
  537. @.C~.C:
  538.     -cd $(<D); $(GET) $(GFLAGS) $(<F)
  539. @.C.c:
  540.     $(CC) $(CFLAGS) -Fc $*.C > $*.c
  541. @.C.o:
  542.     $(CC) $(CFLAGS) -c $*.C
  543. @.C~.o:
  544.     -cd $(<D); $(GET) $(GFLAGS) $(<F)
  545.     $(CC) $(CFLAGS) -c $*.C
  546.  
  547. @//E*O*F Makefile//
  548. chmod u=rw,g=r,o=r Makefile
  549.  
  550. echo x - var.H
  551. sed 's/^@//' > "var.H" <<'@//E*O*F var.H//'
  552. //
  553. // NAME:    var.H
  554. //
  555. // PURPOSE:    C++ Generic "Universal Variable" Class Library Header File
  556. // AUTHOR:    Lee Hounshell
  557. //
  558.  
  559. #ifndef VAR_H
  560. #define VAR_H
  561.  
  562. #include    "string.h"
  563.  
  564. // -----------------------------------------------------------------------------
  565. //
  566. class varsize {
  567.     // dummy class needed for var constructor of specific size that
  568.     // doesn't conflict with the var integer type constructor
  569.     public:
  570.     // Constructors & Destructors
  571.     varsize(int sz);                // constructor
  572.     int size;                    // size of var
  573. };
  574.  
  575. class subvar;
  576.  
  577. // -----------------------------------------------------------------------------
  578. //
  579. class var {
  580.  
  581.     public:
  582.     // Standard Interface
  583.     const var & type(void) const;            // who am i
  584.  
  585.     // Constructors & Destructors
  586.     var(void);                    // constructor
  587.     var(const varsize &);                // constructor
  588.     var(const char *);                // constructor
  589.     var(const char);                // constructor
  590.     var(const short);                // constructor
  591.     var(const unsigned short);            // constructor
  592.     var(const int);                    // constructor
  593.     var(const unsigned int);            // constructor
  594.     var(const long);                // constructor
  595.     var(const unsigned long);            // constructor
  596.     var(const double);                // constructor
  597.     var(const var &);                // copy constructor
  598.     ~var(void);                    // destructor
  599.  
  600.     // Operators
  601.     var & operator = (const char *);        // assignment
  602.         var & operator = (const var &);            // assignment
  603.         char & operator [] (const int);            // indexing
  604.         subvar & operator () (int, int) const;        // substring
  605.         subvar & operator () (const int) const;        // substring
  606.         friend ostream & operator << (ostream &, const var &); // output
  607.         friend istream & operator >> (istream &, var &); // input
  608.     friend class subvar;                // substring
  609.  
  610.     // More Operators (used for arithmetic type extension)
  611.     var & operator = (const char);            // assignment
  612.     var & operator = (const short);            // assignment
  613.     var & operator = (const unsigned short);    // assignment
  614.     var & operator = (const int);            // assignment
  615.     var & operator = (const unsigned int);        // assignment
  616.     var & operator = (const long);            // assignment
  617.     var & operator = (const unsigned long);        // assignment
  618.     var & operator = (const double);        // assignment
  619.  
  620.     // Casting Operators
  621.     operator char * (void) const;            // type conversion
  622.     operator double (void) const;            // type conversion
  623.  
  624.     // Assignment Operators
  625.         var & operator ++ (void);            // increment (pre-index only)
  626.         var & operator -- (void);            // decrement (pre-index only)
  627.         var operator ! (void) const;            // not
  628.  
  629.         var operator + (const var &) const;        // addition OR concatenation
  630.         var operator - (const var &) const;        // subtraction
  631.         var operator * (const var &) const;        // multiplication
  632.         var operator / (const var &) const;        // division
  633.         var operator % (const var &) const;        // remainder
  634.  
  635.         var & operator += (const var &);        // addition OR concatenation
  636.         var & operator -= (const var &);        // subtraction
  637.         var & operator *= (const var &);        // multiplication
  638.         var & operator /= (const var &);        // division
  639.         var & operator %= (const var &);        // remainder
  640.  
  641.         var & operator += (const char &);        // addition OR concatenation
  642.         var & operator += (const char *);        // addition OR concatenation
  643.         var & operator -= (const char *);        // subtraction
  644.         var & operator *= (const char *);        // multiplication
  645.         var & operator /= (const char *);        // division
  646.         var & operator %= (const char *);        // remainder
  647.  
  648.         var & operator += (const double);        // addition OR concatenation
  649.         var & operator -= (const double);        // subtraction
  650.         var & operator *= (const double);        // multiplication
  651.         var & operator /= (const double);        // division
  652.         var & operator %= (const double);        // remainder
  653.  
  654.     friend var operator + (const char *, const var &); // addition OR concatenation
  655.     friend var operator - (const char *, const var &); // subtraction
  656.     friend var operator * (const char *, const var &); // multiplication
  657.     friend var operator / (const char *, const var &); // division
  658.     friend var operator % (const char *, const var &); // remainder
  659.     friend var operator + (const var &, const char *); // addition OR concatenation
  660.     friend var operator - (const var &, const char *); // subtraction
  661.     friend var operator * (const var &, const char *); // multiplication
  662.     friend var operator / (const var &, const char *); // division
  663.     friend var operator % (const var &, const char *); // remainder
  664.  
  665.     friend var operator + (const var &, const double); // addition OR concatenation
  666.     friend var operator - (const var &, const double); // subtraction
  667.     friend var operator * (const var &, const double); // multiplication
  668.     friend var operator / (const var &, const double); // division
  669.     friend var operator % (const var &, const double); // remainder
  670.     friend var operator + (const double, const var &); // addition OR concatenation
  671.     friend var operator - (const double, const var &); // subtraction
  672.     friend var operator * (const double, const var &); // multiplication
  673.     friend var operator / (const double, const var &); // division
  674.     friend var operator % (const double, const var &); // remainder
  675.  
  676.     // Equality Operators
  677.         int operator == (const var &) const;        // equality
  678.         int operator != (const var &) const;        // inequality
  679.         int operator < (const var &) const;        // less than
  680.         int operator > (const var &) const;        // greater than
  681.         int operator <= (const var &) const;        // less than or equal
  682.         int operator >= (const var &) const;        // greater than or equal
  683.  
  684.     friend int operator == (const var &, const char *); // equality
  685.     friend int operator != (const var &, const char *); // inequality
  686.     friend int operator < (const var &, const char *);  // less than
  687.     friend int operator > (const var &, const char *);  // greater than
  688.     friend int operator <= (const var &, const char *); // less than or equal
  689.     friend int operator >= (const var &, const char *); // greater than or equal
  690.     friend int operator == (const char *, const var &); // equality
  691.     friend int operator != (const char *, const var &); // inequality
  692.     friend int operator < (const char *, const var &);  // less than
  693.     friend int operator > (const char *, const var &);  // greater than
  694.     friend int operator <= (const char *, const var &); // less than or equal
  695.     friend int operator >= (const char *, const var &); // greater than or equal
  696.  
  697.     friend int operator == (const var &, const double); // equality
  698.     friend int operator != (const var &, const double); // inequality
  699.     friend int operator < (const var &, const double);  // less than
  700.     friend int operator > (const var &, const double);  // greater than
  701.     friend int operator <= (const var &, const double); // less than or equal
  702.     friend int operator >= (const var &, const double); // greater than or equal
  703.     friend int operator == (const double, const var &); // equality
  704.     friend int operator != (const double, const var &); // inequality
  705.     friend int operator < (const double, const var &);  // less than
  706.     friend int operator > (const double, const var &);  // greater than
  707.     friend int operator <= (const double, const var &); // less than or equal
  708.     friend int operator >= (const double, const var &); // greater than or equal
  709.  
  710.     // Custom Interface
  711.     void null(int);                    // "null" out string
  712.     void changesize(int);                // change allocated memory
  713.     int length(void) const;                // length of string
  714.     const char * vartype(void) const;        // name of this var type
  715.     void change_type(const char *);            // change var type
  716.     int is_string(void) const;            // test var type
  717.     int is_double(void) const;            // test var type
  718.     int is_long(void) const;            // test var type
  719.     int strchr(const char) const;            // strchr(char) index
  720.     int strrchr(const char) const;            // strrchr(char) index
  721.     var & concat(const var &);            // concatenation
  722.     var & format(const char *);            // set output format
  723.     void print(ostream &) const;            // output
  724.     void read(istream &);                // input
  725.  
  726.     static int save_me;                // cntrl object input
  727.     static int save_it(const int save_flag = var::save_me); // input ctrl
  728.  
  729.     protected:
  730.  
  731.     private:
  732.     int    numcheck(const char *) const;        // determine is_numeric value
  733.  
  734.     static    const var ctype;            // for type() function
  735.     short    fixed;                    // 1=fixed data type
  736.     short    is_numeric;                // 0=string, 1=short/int/long, 2=float/double
  737.     int    data_str_len;                // length of allocated "string"
  738.     int    data_str_end;                // index to current "end" of string
  739.     char    *data_str;                // for "string" data
  740.     char    *format_str;                // the input/output format string
  741.  
  742. };
  743.  
  744.  
  745. class subvar : public var {
  746.     public:
  747.         var & operator = (const var &);            // substring replacement
  748.     var        *varptr;
  749.     unsigned    offset;
  750.     unsigned    length;
  751. };
  752.  
  753. #endif
  754.  
  755. @//E*O*F var.H//
  756. chmod u=rw,g=r,o=r var.H
  757.  
  758. echo x - var.C
  759. sed 's/^@//' > "var.C" <<'@//E*O*F var.C//'
  760. //
  761. // NAME:    var.C
  762. //
  763. // PURPOSE:    C++ Generic "Universal Variable" library class
  764. // AUTHOR:    Lee Hounshell
  765. //
  766.  
  767. #include    <stddef.h>
  768. #include    <stream.h>
  769. #include    <stdlib.h>
  770. #include    <ctype.h>
  771. #include    <string.h>
  772. #include    "var.H"
  773. #include    "Misc.H"
  774.  
  775. const int    VAR_PAD_SIZE        = 128;
  776. const int    VAR_DEF_SIZE        = 16;
  777.  
  778. const short    VAR_STRING        = 0;
  779. const short    VAR_LONG        = 1;
  780. const short    VAR_DOUBLE        = 2;
  781.  
  782. char *    DEFAULT_STRING_FORMAT        = "'%s'";
  783. char *    DEFAULT_INT_FORMAT        = "%d";
  784. char *    DEFAULT_UINT_FORMAT        = "%u";
  785. char *    DEFAULT_LONG_FORMAT        = "%ld";
  786. char *    DEFAULT_ULONG_FORMAT        = "%lu";
  787. char *    DEFAULT_DOUBLE_FORMAT        = "%9.2f";
  788.  
  789. // -----------------------------------------------------------------------------
  790.  
  791. const var var::ctype    = "var";
  792. int var::save_me            = 1;
  793.  
  794.  
  795. const var & var::type(void) const
  796. {
  797.     return var::ctype;
  798. }
  799.  
  800.  
  801. varsize::varsize(int sz)
  802. {
  803.     size = sz;
  804. }
  805.  
  806.  
  807. var::var(void)
  808. {
  809.     fixed = 0;
  810.     is_numeric = VAR_STRING;
  811.     data_str_len = VAR_DEF_SIZE;
  812.     data_str_end = 0;
  813.     data_str = new char[data_str_len];
  814.     data_str[0] = 0;
  815.     format_str = DEFAULT_STRING_FORMAT;
  816. }
  817.  
  818.  
  819. var::var(const char *str)
  820. {
  821.     fixed = 1;
  822.     is_numeric = VAR_STRING;
  823.     data_str_end = strlen(str);
  824.     data_str_len = data_str_end + VAR_DEF_SIZE;
  825.     data_str = new char[data_str_len];
  826.     strcpy(data_str, str);
  827.     format_str = DEFAULT_STRING_FORMAT;
  828. }
  829.  
  830.  
  831. var::var(const varsize &vsz)
  832. {
  833.     fixed = 0;
  834.     is_numeric = VAR_STRING;
  835.     data_str_len = vsz.size + VAR_DEF_SIZE;
  836.     data_str_end = 0;
  837.     data_str = new char[data_str_len];
  838.     data_str[0] = 0;
  839.     format_str = DEFAULT_STRING_FORMAT;
  840. }
  841.  
  842.  
  843. var::var(const char ch)
  844. {
  845.     fixed = 0;
  846.     is_numeric = VAR_STRING;
  847.     data_str_len = VAR_DEF_SIZE;
  848.     data_str_end = 1;
  849.     data_str = new char[data_str_len];
  850.     data_str[0] = ch;
  851.     data_str[1] = 0;
  852.     format_str = DEFAULT_STRING_FORMAT;
  853. }
  854.  
  855.  
  856. var::var(const short int_num)
  857. {
  858.     fixed = 1;
  859.     is_numeric = VAR_LONG;
  860.     data_str_len = VAR_DEF_SIZE;
  861.     data_str = new char[data_str_len];
  862.     strcpy(data_str, itoa(int_num));
  863.     data_str_end = strlen(data_str);
  864.     format_str = DEFAULT_INT_FORMAT;
  865. }
  866.  
  867.  
  868. var::var(const unsigned short int_num)
  869. {
  870.     fixed = 1;
  871.     is_numeric = VAR_LONG;
  872.     data_str_len = VAR_DEF_SIZE;
  873.     data_str = new char[data_str_len];
  874.     strcpy(data_str, itoa(int_num));
  875.     data_str_end = strlen(data_str);
  876.     format_str = DEFAULT_UINT_FORMAT;
  877. }
  878.  
  879.  
  880. var::var(const int int_num)
  881. {
  882.     fixed = 1;
  883.     is_numeric = VAR_LONG;
  884.     data_str_len = VAR_DEF_SIZE;
  885.     data_str = new char[data_str_len];
  886.     strcpy(data_str, itoa(int_num));
  887.     data_str_end = strlen(data_str);
  888.     format_str = DEFAULT_INT_FORMAT;
  889. }
  890.  
  891.  
  892. var::var(const unsigned int int_num)
  893. {
  894.     fixed = 1;
  895.     is_numeric = VAR_LONG;
  896.     data_str_len = VAR_DEF_SIZE;
  897.     data_str = new char[data_str_len];
  898.     strcpy(data_str, itoa(int_num));
  899.     data_str_end = strlen(data_str);
  900.     format_str = DEFAULT_UINT_FORMAT;
  901. }
  902.  
  903.  
  904. var::var(const long long_num)
  905. {
  906.     fixed = 1;
  907.     is_numeric = VAR_LONG;
  908.     data_str_len = VAR_DEF_SIZE;
  909.     data_str = new char[data_str_len];
  910.     strcpy(data_str, ltoa(long_num));
  911.     data_str_end = strlen(data_str);
  912.     format_str = DEFAULT_LONG_FORMAT;
  913. }
  914.  
  915.  
  916. var::var(const unsigned long long_num)
  917. {
  918.     fixed = 1;
  919.     is_numeric = VAR_LONG;
  920.     data_str_len = VAR_DEF_SIZE;
  921.     data_str = new char[data_str_len];
  922.     strcpy(data_str, ltoa(long_num));
  923.     data_str_end = strlen(data_str);
  924.     format_str = DEFAULT_ULONG_FORMAT;
  925. }
  926.  
  927.  
  928. var::var(const double double_num)
  929. {
  930.     fixed = 1;
  931.     is_numeric = VAR_DOUBLE;
  932.     data_str_len = VAR_DEF_SIZE;
  933.     data_str = new char[data_str_len];
  934.     strcpy(data_str, dtoa(double_num));
  935.     data_str_end = strlen(data_str);
  936.     format_str = DEFAULT_DOUBLE_FORMAT;
  937. }
  938.  
  939.  
  940. var::var(const var &v)
  941. {
  942.     fixed = v.fixed;
  943.     is_numeric = v.is_numeric;
  944.     if (v.data_str && v.data_str_end) {
  945.     data_str_len = v.data_str_end + VAR_DEF_SIZE;
  946.     data_str_end = v.data_str_end;
  947.     data_str = new char[data_str_len];
  948.     strcpy(data_str, v.data_str);
  949.     }
  950.     else {
  951.     data_str_len = VAR_DEF_SIZE;
  952.     data_str_end = 0;
  953.     data_str = new char[data_str_len];
  954.     data_str[0] = 0;
  955.     }
  956.     format_str = DEFAULT_STRING_FORMAT;
  957. }
  958.  
  959.  
  960. var::~var(void)
  961. {
  962.     if (data_str) {
  963.     delete data_str;
  964.     }
  965.     if (format_str
  966.     && format_str != DEFAULT_STRING_FORMAT
  967.     && format_str != DEFAULT_INT_FORMAT
  968.     && format_str != DEFAULT_UINT_FORMAT
  969.     && format_str != DEFAULT_LONG_FORMAT
  970.     && format_str != DEFAULT_ULONG_FORMAT
  971.     && format_str != DEFAULT_DOUBLE_FORMAT) {
  972.         delete format_str;
  973.     }
  974. }
  975.  
  976. // -----------------------------------------------------------------------------
  977.  
  978. var & var::operator = (const char *str)
  979. {
  980.     if (fixed && is_numeric) {
  981.     if (is_numeric == VAR_DOUBLE) {
  982.         double d = atod((char *) str);
  983.         *this = d;
  984.     }
  985.     else {
  986.         long l = atol(str);
  987.         *this = l;
  988.     }
  989.     }
  990.     else {
  991.     int len = strlen(str) + 1;
  992.     if (data_str_len < len) {
  993.         delete data_str;
  994.         data_str_len = len;
  995.         data_str = new char[data_str_len];
  996.     }
  997.     data_str_end = len - 1;
  998.     strcpy(data_str, str);
  999.     if (!fixed) {
  1000.         int str_is_numeric = numcheck(data_str);
  1001.         is_numeric = str_is_numeric;
  1002.     }
  1003.     }
  1004.     return *this;
  1005. }
  1006.  
  1007.  
  1008. var & var::operator = (const var &l)
  1009. {
  1010.     if (this != &l) {
  1011.     if (data_str_len <= l.data_str_end) {
  1012.         delete data_str;
  1013.         data_str_len = l.data_str_end + VAR_DEF_SIZE;
  1014.         data_str = new char[data_str_len];
  1015.     }
  1016.     data_str_end = l.data_str_end;
  1017.     strncpy(data_str, l.data_str, l.data_str_end);
  1018.     data_str[data_str_end] = 0;
  1019.     if (!fixed) {
  1020.         is_numeric = numcheck(data_str);
  1021.     }
  1022.     //
  1023.     // Note: the output "format" of a var variable is preserved
  1024.     //
  1025.     }
  1026.     return *this;
  1027. }
  1028.  
  1029.  
  1030. char & var::operator [] (const int index)
  1031. {
  1032.     static char error_ch;
  1033.     if (index < 0) {
  1034.     cerr << "ERROR: " << " - var[" << index << "] negative index used." << endl;
  1035.     error_ch = 0;
  1036.     return error_ch;
  1037.     }
  1038.     if (data_str_len <= index) {
  1039.     // this is technically a program error, but I'll be nice and extend the string's length
  1040.     data_str_len = index + VAR_PAD_SIZE;
  1041.     data_str_end = index + 1;
  1042.     char *buf = new char[data_str_len];
  1043.     sprintf(buf, "%-*.*s", data_str_end, data_str_end, data_str);
  1044.     delete data_str;
  1045.     data_str = buf;
  1046.     data_str[index] = 0;
  1047.     cerr << "WARNING: " << " - var index '" << index << "' beyond current string boundary." << endl;
  1048.     }
  1049.     while (data_str_end < index) {
  1050.     data_str[data_str_end++] = ' ';        // pad to index with spaces if necessary
  1051.     }
  1052.     if (data_str_end == index) {
  1053.     data_str[data_str_end] = 0;        // the end of a string is ALWAYS 0
  1054.     if ((data_str_end + 1) < data_str_len) {
  1055.         data_str[++data_str_end] = 0;    // the new end of string is also 0
  1056.     }
  1057.     }
  1058.     return data_str[index];
  1059. }
  1060.  
  1061.  
  1062. // for substrings
  1063. subvar & var::operator () (const int offset) const
  1064. {
  1065.     return operator () (offset, -1);
  1066. }
  1067.  
  1068.  
  1069. // for substrings
  1070. subvar & var::operator () (int offset, int length) const
  1071. {
  1072.     static subvar _esi_subvar;
  1073.     if (length < 0) {
  1074.     length = data_str_end - offset;
  1075.     }
  1076.     char *substr = new char[length + 1];
  1077.     strncpy(substr, data_str + offset, (int) length);
  1078.     substr[length] = 0;
  1079.     _esi_subvar.var::operator = (substr);
  1080.     _esi_subvar.varptr = (var *) this;
  1081.     _esi_subvar.offset = offset;
  1082.     _esi_subvar.length = length;
  1083.     delete substr;
  1084.     return _esi_subvar;
  1085. }
  1086.  
  1087.  
  1088. // for syntax: var(offset, length) = var
  1089. var & subvar::operator = (const var &substr)
  1090. {
  1091.     char *srcstr = varptr->data_str;
  1092.     char *repstr = substr.data_str;
  1093.     int replen = length;
  1094.     if (substr.data_str_end < length) {
  1095.     replen = substr.data_str_end;
  1096.     }
  1097.     int len = varptr->data_str_len;
  1098.     char *newstr = new char[len];
  1099.     strncpy(newstr, srcstr, offset);        // data from string being replaced up to "offset"
  1100.     if (replen) {
  1101.     strncpy(newstr + offset, repstr, replen);    // replacement string data
  1102.     }
  1103.     int newoffset = offset + replen;
  1104.     if (newoffset < varptr->data_str_end) {
  1105.     strcpy(newstr + newoffset, srcstr + offset + length);
  1106.     }
  1107.     else {
  1108.     newstr[newoffset] = 0;
  1109.     }
  1110.     if (varptr->data_str) {
  1111.     delete varptr->data_str;
  1112.     }
  1113.     varptr->data_str = newstr;
  1114.     varptr->data_str_len = len;
  1115.     varptr->data_str_end = strlen(newstr);
  1116.     if (!varptr->fixed) {
  1117.     varptr->is_numeric = numcheck(newstr);
  1118.     }
  1119.     return *varptr;
  1120. }
  1121.  
  1122. // -----------------------------------------------------------------------------
  1123.  
  1124. var & var::operator = (const char ch)
  1125. {
  1126.     char buf[2];
  1127.     buf[0] = ch;
  1128.     buf[1] = 0;
  1129.     *this = buf;
  1130.     return *this;
  1131. }
  1132.  
  1133.  
  1134. var & var::operator = (const short int_num)
  1135. {
  1136.     char *str = itoa(int_num);
  1137.     int len = strlen(str);
  1138.     if (data_str_len < len) {
  1139.     delete data_str;
  1140.     data_str_len = len + 1;
  1141.     data_str = new char[data_str_len];
  1142.     }
  1143.     data_str_end = len;
  1144.     strcpy(data_str, str);
  1145.     if (!fixed) {
  1146.     is_numeric = VAR_LONG;
  1147.     }
  1148.     return *this;
  1149. }
  1150.  
  1151.  
  1152. var & var::operator = (const unsigned short int_num)
  1153. {
  1154.     char *str = itoa(int_num);
  1155.     int len = strlen(str);
  1156.     if (data_str_len < len) {
  1157.     delete data_str;
  1158.     data_str_len = len + 1;
  1159.     data_str = new char[data_str_len];
  1160.     }
  1161.     data_str_end = len;
  1162.     strcpy(data_str, str);
  1163.     is_numeric = VAR_LONG;
  1164.     return *this;
  1165. }
  1166.  
  1167.  
  1168. var & var::operator = (const int int_num)
  1169. {
  1170.     char *str = itoa(int_num);
  1171.     int len = strlen(str);
  1172.     if (data_str_len < len) {
  1173.     delete data_str;
  1174.     data_str_len = len + 1;
  1175.     data_str = new char[data_str_len];
  1176.     }
  1177.     data_str_end = len;
  1178.     strcpy(data_str, str);
  1179.     if (!fixed) {
  1180.     is_numeric = VAR_LONG;
  1181.     }
  1182.     return *this;
  1183. }
  1184.  
  1185.  
  1186. var & var::operator = (const unsigned int int_num)
  1187. {
  1188.     char *str = itoa(int_num);
  1189.     int len = strlen(str);
  1190.     if (data_str_len < len) {
  1191.     delete data_str;
  1192.     data_str_len = len + 1;
  1193.     data_str = new char[data_str_len];
  1194.     }
  1195.     data_str_end = len;
  1196.     strcpy(data_str, str);
  1197.     if (!fixed) {
  1198.     is_numeric = VAR_LONG;
  1199.     }
  1200.     return *this;
  1201. }
  1202.  
  1203.  
  1204. var & var::operator = (const long long_num)
  1205. {
  1206.     char *str = ltoa(long_num);
  1207.     int len = strlen(str);
  1208.     if (data_str_len < len) {
  1209.     delete data_str;
  1210.     data_str_len = len + 1;
  1211.     data_str = new char[data_str_len];
  1212.     }
  1213.     data_str_end = len;
  1214.     strcpy(data_str, str);
  1215.     if (!fixed) {
  1216.     is_numeric = VAR_LONG;
  1217.     }
  1218.     return *this;
  1219. }
  1220.  
  1221.  
  1222. var & var::operator = (const unsigned long long_num)
  1223. {
  1224.     char *str = ltoa(long_num);
  1225.     int len = strlen(str);
  1226.     if (data_str_len < len) {
  1227.     delete data_str;
  1228.     data_str_len = len + 1;
  1229.     data_str = new char[data_str_len];
  1230.     }
  1231.     data_str_end = len;
  1232.     strcpy(data_str, str);
  1233.     if (!fixed) {
  1234.     is_numeric = VAR_LONG;
  1235.     }
  1236.     return *this;
  1237. }
  1238.  
  1239.  
  1240. var & var::operator = (const double dbl_num)
  1241. {
  1242.     char *str = dtoa(dbl_num);
  1243.     int len = strlen(str);
  1244.     if (data_str_len < len) {
  1245.     delete data_str;
  1246.     data_str_len = len + 1;
  1247.     data_str = new char[data_str_len];
  1248.     }
  1249.     data_str_end = len;
  1250.     strcpy(data_str, str);
  1251.     if (!fixed) {
  1252.     is_numeric = VAR_DOUBLE;
  1253.     }
  1254.     return *this;
  1255. }
  1256.  
  1257. // -----------------------------------------------------------------------------
  1258.  
  1259. var::operator char * (void) const
  1260. {
  1261.     return data_str;
  1262. }
  1263.  
  1264.  
  1265. var::operator double (void) const
  1266. {
  1267.     return atod(data_str);
  1268. }
  1269.  
  1270. // -----------------------------------------------------------------------------
  1271.  
  1272. var & var::operator ++ (void)        // increment (pre-index only)
  1273. {
  1274.     *this += 1;
  1275.     return *this;
  1276. }
  1277.  
  1278.  
  1279. var & var::operator -- (void)        // decrement (pre-index only)
  1280. {
  1281.     *this -= 1;
  1282.     return *this;
  1283. }
  1284.  
  1285.  
  1286. var var::operator ! (void) const    // not
  1287. {
  1288.     var not(1);
  1289.     if ((int) *this) {
  1290.     not = 0;
  1291.     }
  1292.     return not;
  1293. }
  1294.  
  1295. // -----------------------------------------------------------------------------
  1296.  
  1297. var var::operator + (const var & v) const    // addition OR concatenation
  1298. {
  1299.     var add;
  1300.     if (is_numeric && v.is_numeric) {
  1301.     // do math in the highest precision specified
  1302.     int n_type = (is_numeric > v.is_numeric) ? is_numeric : v.is_numeric;
  1303.     switch (n_type) {
  1304.         case VAR_LONG:
  1305.         add = (long) *this + (long) v;
  1306.         break;
  1307.         default:
  1308.         // should be VAR_DOUBLE
  1309.         add = (double) *this + (double) v;
  1310.         break;
  1311.     }
  1312.     }
  1313.     else {
  1314.     // concatenate strings
  1315.     delete add.data_str;
  1316.     add.data_str_len = data_str_end + v.data_str_end + VAR_PAD_SIZE;
  1317.     add.data_str_end = data_str_end + v.data_str_end;
  1318.     add.data_str = new char[add.data_str_len];
  1319.     strcpy(add.data_str, data_str);
  1320.     strcpy((add.data_str) + data_str_end, v.data_str);
  1321.     add.is_numeric = VAR_STRING;
  1322.     }
  1323.     return add;
  1324. }
  1325.  
  1326.  
  1327. var var::operator - (const var & v) const    // subtraction
  1328. {
  1329.     var sub;
  1330.     // do math in the highest precision specified
  1331.     int n_type = (is_numeric > v.is_numeric) ? is_numeric : v.is_numeric;
  1332.     switch (n_type) {
  1333.     case VAR_LONG:
  1334.         sub = (long) *this - (long) v;
  1335.         sub.is_numeric = VAR_LONG;
  1336.         break;
  1337.     default:
  1338.         // should be VAR_DOUBLE
  1339.         sub = (double) *this - (double) v;
  1340.         break;
  1341.     }
  1342.     return sub;
  1343. }
  1344.  
  1345.  
  1346. var var::operator * (const var & v) const    // multiplication
  1347. {
  1348.     var times;
  1349.     // do math in the highest precision specified
  1350.     int n_type = (is_numeric > v.is_numeric) ? is_numeric : v.is_numeric;
  1351.     switch (n_type) {
  1352.     case VAR_LONG:
  1353.         times = (long) *this * (long) v;
  1354.         break;
  1355.     default:
  1356.         // should be VAR_DOUBLE
  1357.         times = (double) *this * (double) v;
  1358.         break;
  1359.     }
  1360.     return times;
  1361. }
  1362.  
  1363.  
  1364. var var::operator / (const var & v) const    // division
  1365. {
  1366.     var div;
  1367.     // do math in the highest precision specified
  1368.     int n_type = (is_numeric > v.is_numeric) ? is_numeric : v.is_numeric;
  1369.     switch (n_type) {
  1370.     case VAR_LONG:
  1371.         div = (long) *this / (long) v;
  1372.         break;
  1373.     default:
  1374.         // should be VAR_DOUBLE
  1375.         div = (double) *this / (double) v;
  1376.         break;
  1377.     }
  1378.     return div;
  1379. }
  1380.  
  1381.  
  1382. var var::operator % (const var & v) const    // remainder
  1383. {
  1384.     var mod;
  1385.     // do math in the highest precision specified
  1386.     int n_type = (is_numeric > v.is_numeric) ? is_numeric : v.is_numeric;
  1387.     switch (n_type) {
  1388.     case VAR_LONG:
  1389.         mod = (long) *this % (long) v;
  1390.         break;
  1391.     default:
  1392.         // should be VAR_DOUBLE
  1393.         // really, I shouldn't allow this..
  1394.         mod = (double) ((long) *this % (long) v);
  1395.         break;
  1396.     }
  1397.     return mod;
  1398. }
  1399.  
  1400. // -----------------------------------------------------------------------------
  1401.  
  1402. var & var::operator += (const var & v)
  1403. {
  1404.     if ((is_numeric == VAR_STRING) || (v.is_numeric == VAR_STRING)) {
  1405.     concat(v);
  1406.     }
  1407.     else {
  1408.     *this = (*this) + v;
  1409.     }
  1410.     return *this;
  1411. }
  1412.  
  1413.  
  1414. var & var::operator -= (const var & v)
  1415. {
  1416.     *this = (*this) - v;
  1417.     return *this;
  1418. }
  1419.  
  1420.  
  1421. var & var::operator *= (const var & v)
  1422. {
  1423.     *this = (*this) * v;
  1424.     return *this;
  1425. }
  1426.  
  1427.  
  1428. var & var::operator /= (const var & v)
  1429. {
  1430.     *this = (*this) / v;
  1431.     return *this;
  1432. }
  1433.  
  1434.  
  1435. var & var::operator %= (const var & v)
  1436. {
  1437.     *this = (*this) % v;
  1438.     return *this;
  1439. }
  1440.  
  1441. // -----------------------------------------------------------------------------
  1442.  
  1443. var & var::operator += (const char & ch)
  1444. {
  1445.     var foo = ch;
  1446.     *this += foo;
  1447.     return *this;
  1448. }
  1449.  
  1450. var & var::operator += (const char * v)
  1451. {
  1452.     var foo = v;
  1453.     *this += foo;
  1454.     return *this;
  1455. }
  1456.  
  1457.  
  1458. var & var::operator -= (const char * v)
  1459. {
  1460.     var foo = v;
  1461.     *this -= foo;
  1462.     return *this;
  1463. }
  1464.  
  1465.  
  1466. var & var::operator *= (const char * v)
  1467. {
  1468.     var foo = v;
  1469.     *this *= foo;
  1470.     return *this;
  1471. }
  1472.  
  1473.  
  1474. var & var::operator /= (const char * v)
  1475. {
  1476.     var foo = v;
  1477.     *this /= foo;
  1478.     return *this;
  1479. }
  1480.  
  1481.  
  1482. var & var::operator %= (const char * v)
  1483. {
  1484.     var foo = v;
  1485.     *this %= foo;
  1486.     return *this;
  1487. }
  1488.  
  1489. // -----------------------------------------------------------------------------
  1490.  
  1491. var & var::operator += (const double v)
  1492. {
  1493.     var foo = v;
  1494.     *this += foo;
  1495.     return *this;
  1496. }
  1497.  
  1498.  
  1499. var & var::operator -= (const double v)
  1500. {
  1501.     var foo = v;
  1502.     *this -= foo;
  1503.     return *this;
  1504. }
  1505.  
  1506.  
  1507. var & var::operator *= (const double v)
  1508. {
  1509.     var foo = v;
  1510.     *this *= foo;
  1511.     return *this;
  1512. }
  1513.  
  1514.  
  1515. var & var::operator /= (const double v)
  1516. {
  1517.     var foo = v;
  1518.     *this /= foo;
  1519.     return *this;
  1520. }
  1521.  
  1522.  
  1523. var & var::operator %= (const double v)
  1524. {
  1525.     var foo = v;
  1526.     *this %= foo;
  1527.     return *this;
  1528. }
  1529.  
  1530. // -----------------------------------------------------------------------------
  1531.  
  1532. var operator + (const char * s, const var & v)
  1533. {
  1534.     var foo = s;
  1535.     return foo + v;
  1536. }
  1537.  
  1538.  
  1539. var operator - (const char * s, const var & v)
  1540. {
  1541.     var foo = s;
  1542.     return foo - v;
  1543. }
  1544.  
  1545.  
  1546. var operator * (const char * s, const var & v)
  1547. {
  1548.     var foo = s;
  1549.     return foo * v;
  1550. }
  1551.  
  1552.  
  1553. var operator / (const char * s, const var & v)
  1554. {
  1555.     var foo = s;
  1556.     return foo / v;
  1557. }
  1558.  
  1559.  
  1560. var operator % (const char * s, const var & v)
  1561. {
  1562.     var foo = s;
  1563.     return foo % v;
  1564. }
  1565.  
  1566.  
  1567. var operator + (const var & v, const char * s)
  1568. {
  1569.     var foo = s;
  1570.     return v + foo;
  1571. }
  1572.  
  1573.  
  1574. var operator - (const var & v, const char * s)
  1575. {
  1576.     var foo = s;
  1577.     return v - foo;
  1578. }
  1579.  
  1580.  
  1581. var operator * (const var & v, const char * s)
  1582. {
  1583.     var foo = s;
  1584.     return v * foo;
  1585. }
  1586.  
  1587.  
  1588. var operator / (const var & v, const char * s)
  1589. {
  1590.     var foo = s;
  1591.     return v / foo;
  1592. }
  1593.  
  1594.  
  1595. var operator % (const var & v, const char * s)
  1596. {
  1597.     var foo = s;
  1598.     return v % foo;
  1599. }
  1600.  
  1601. // -----------------------------------------------------------------------------
  1602.  
  1603. var operator + (const var & v, const double d)
  1604. {
  1605.     var foo = d;
  1606.     return v + foo;
  1607. }
  1608.  
  1609.  
  1610. var operator - (const var & v, const double d)
  1611. {
  1612.     var foo = d;
  1613.     return v - foo;
  1614. }
  1615.  
  1616.  
  1617. var operator * (const var & v, const double d)
  1618. {
  1619.     var foo = d;
  1620.     return v * foo;
  1621. }
  1622.  
  1623.  
  1624. var operator / (const var & v, const double d)
  1625. {
  1626.     var foo = d;
  1627.     return v / foo;
  1628. }
  1629.  
  1630.  
  1631. var operator % (const var & v, const double d)
  1632. {
  1633.     var foo = d;
  1634.     return v % foo;
  1635. }
  1636.  
  1637.  
  1638. var operator + (const double d, const var & v)
  1639. {
  1640.     var foo = d;
  1641.     return foo + v;
  1642. }
  1643.  
  1644.  
  1645. var operator - (const double d, const var & v)
  1646. {
  1647.     var foo = d;
  1648.     return foo - v;
  1649. }
  1650.  
  1651.  
  1652. var operator * (const double d, const var & v)
  1653. {
  1654.     var foo = d;
  1655.     return foo * v;
  1656. }
  1657.  
  1658.  
  1659. var operator / (const double d, const var & v)
  1660. {
  1661.     var foo = d;
  1662.     return foo / v;
  1663. }
  1664.  
  1665.  
  1666. var operator % (const double d, const var & v)
  1667. {
  1668.     var foo = d;
  1669.     return foo % v;
  1670. }
  1671.  
  1672. // -----------------------------------------------------------------------------
  1673.  
  1674. int var::operator == (const var & t) const        // equality
  1675. {
  1676.     if (is_numeric && t.is_numeric) {
  1677.     if (is_numeric == VAR_LONG && t.is_numeric == VAR_LONG) {
  1678.         return (long) (*this) == (long) t;
  1679.     }
  1680.     return (double) (*this) == (double) t;
  1681.     }
  1682.     else {
  1683.     if (data_str_end && t.data_str_end) {
  1684.         return !strcmp(data_str, t.data_str);
  1685.     }
  1686.     else {
  1687.         return data_str_end == t.data_str_end;
  1688.     }
  1689.     }
  1690. }
  1691.  
  1692.  
  1693. int var::operator != (const var & t) const        // inequality
  1694. {
  1695.     if (is_numeric && t.is_numeric) {
  1696.     if (is_numeric == VAR_LONG && t.is_numeric == VAR_LONG) {
  1697.         return (long) (*this) != (long) t;
  1698.     }
  1699.     return (double) (*this) != (double) t;
  1700.     }
  1701.     else {
  1702.     if (data_str_end && t.data_str_end) {
  1703.         return strcmp(data_str, t.data_str);
  1704.     }
  1705.     else {
  1706.         return data_str_end != t.data_str_end;
  1707.     }
  1708.     }
  1709. }
  1710.  
  1711.  
  1712. int var::operator < (const var & t) const        // less than
  1713. {
  1714.     if (is_numeric && t.is_numeric) {
  1715.     if (is_numeric == VAR_LONG && t.is_numeric == VAR_LONG) {
  1716.         return (long) (*this) < (long) t;
  1717.     }
  1718.     return (double) (*this) < (double) t;
  1719.     }
  1720.     else {
  1721.     if (data_str_end && t.data_str_end) {
  1722.         return (strcmp(data_str, t.data_str) < 0);
  1723.     }
  1724.     else {
  1725.         return data_str_end < t.data_str_end;
  1726.     }
  1727.     }
  1728. }
  1729.  
  1730.  
  1731. int var::operator > (const var & t) const        // greater than
  1732. {
  1733.     if (is_numeric && t.is_numeric) {
  1734.     if (is_numeric == VAR_LONG && t.is_numeric == VAR_LONG) {
  1735.         return (long) (*this) > (long) t;
  1736.     }
  1737.     return (double) (*this) > (double) t;
  1738.     }
  1739.     else {
  1740.     if (data_str_end && t.data_str_end) {
  1741.         return (strcmp(data_str, t.data_str) > 0);
  1742.     }
  1743.     else {
  1744.         return data_str_end > t.data_str_end;
  1745.     }
  1746.     }
  1747. }
  1748.  
  1749.  
  1750. int var::operator <= (const var & t) const        // less than or equal
  1751. {
  1752.     if (is_numeric && t.is_numeric) {
  1753.     if (is_numeric == VAR_LONG && t.is_numeric == VAR_LONG) {
  1754.         return (long) (*this) <= (long) t;
  1755.     }
  1756.     return (double) (*this) <= (double) t;
  1757.     }
  1758.     else {
  1759.     if (data_str_end && t.data_str_end) {
  1760.         return (strcmp(data_str, t.data_str) <= 0);
  1761.     }
  1762.     else {
  1763.         return data_str_end <= t.data_str_end;
  1764.     }
  1765.     }
  1766. }
  1767.  
  1768.  
  1769. int var::operator >= (const var & t) const        // greater than or equal
  1770. {
  1771.     if (is_numeric && t.is_numeric) {
  1772.     if (is_numeric == VAR_LONG && t.is_numeric == VAR_LONG) {
  1773.         return (long) (*this) >= (long) t;
  1774.     }
  1775.     return (double) (*this) >= (double) t;
  1776.     }
  1777.     else {
  1778.     if (data_str_end && t.data_str_end) {
  1779.         return (strcmp(data_str, t.data_str) >= 0);
  1780.     }
  1781.     else {
  1782.         return data_str_end >= t.data_str_end;
  1783.     }
  1784.     }
  1785. }
  1786.  
  1787. // -----------------------------------------------------------------------------
  1788.  
  1789. int operator == (const var & t, const char * s)
  1790. {
  1791.     var foo = s;
  1792.     return t == foo;
  1793. }
  1794.  
  1795.  
  1796. int operator != (const var & t, const char * s)
  1797. {
  1798.     var foo = s;
  1799.     return t != foo;
  1800. }
  1801.  
  1802.  
  1803. int operator < (const var & t, const char * s)
  1804. {
  1805.     var foo = s;
  1806.     return t < foo;
  1807. }
  1808.  
  1809.  
  1810. int operator > (const var & t, const char * s)
  1811. {
  1812.     var foo = s;
  1813.     return t > foo;
  1814. }
  1815.  
  1816.  
  1817. int operator <= (const var & t, const char * s)
  1818. {
  1819.     var foo = s;
  1820.     return t <= foo;
  1821. }
  1822.  
  1823.  
  1824. int operator >= (const var & t, const char * s)
  1825. {
  1826.     var foo = s;
  1827.     return t >= foo;
  1828. }
  1829.  
  1830.  
  1831. int operator == (const char * s, const var & t)
  1832. {
  1833.     var foo = s;
  1834.     return foo == t;
  1835. }
  1836.  
  1837.  
  1838. int operator != (const char * s, const var & t)
  1839. {
  1840.     var foo = s;
  1841.     return foo != t;
  1842. }
  1843.  
  1844.  
  1845. int operator < (const char * s, const var & t)
  1846. {
  1847.     var foo = s;
  1848.     return foo < t;
  1849. }
  1850.  
  1851.  
  1852. int operator > (const char * s, const var & t)
  1853. {
  1854.     var foo = s;
  1855.     return foo > t;
  1856. }
  1857.  
  1858.  
  1859. int operator <= (const char * s, const var & t)
  1860. {
  1861.     var foo = s;
  1862.     return foo <= t;
  1863. }
  1864.  
  1865.  
  1866. int operator >= (const char * s, const var & t)
  1867. {
  1868.     var foo = s;
  1869.     return foo >= t;
  1870. }
  1871.  
  1872. // -----------------------------------------------------------------------------
  1873.  
  1874. int operator == (const var & t, const double d)
  1875. {
  1876.     return (double) t == d;
  1877. }
  1878.  
  1879.  
  1880. int operator != (const var & t, const double d)
  1881. {
  1882.     return (double) t != d;
  1883. }
  1884.  
  1885.  
  1886. int operator < (const var & t, const double d)
  1887. {
  1888.     return (double) t < d;
  1889. }
  1890.  
  1891.  
  1892. int operator > (const var & t, const double d)
  1893. {
  1894.     return (double) t > d;
  1895. }
  1896.  
  1897.  
  1898. int operator <= (const var & t, const double d)
  1899. {
  1900.     return (double) t <= d;
  1901. }
  1902.  
  1903.  
  1904. int operator >= (const var & t, const double d)
  1905. {
  1906.     return (double) t >= d;
  1907. }
  1908.  
  1909.  
  1910. int operator == (const double d, const var & t)
  1911. {
  1912.     return d == (double) t;
  1913. }
  1914.  
  1915.  
  1916. int operator != (const double d, const var & t)
  1917. {
  1918.     return d != (double) t;
  1919. }
  1920.  
  1921.  
  1922. int operator < (const double d, const var & t)
  1923. {
  1924.     return d < (double) t;
  1925. }
  1926.  
  1927.  
  1928. int operator > (const double d, const var & t)
  1929. {
  1930.     return d > (double) t;
  1931. }
  1932.  
  1933.  
  1934. int operator <= (const double d, const var & t)
  1935. {
  1936.     return d <= (double) t;
  1937. }
  1938.  
  1939.  
  1940. int operator >= (const double d, const var & t)
  1941. {
  1942.     return d >= (double) t;
  1943. }
  1944.  
  1945. // -----------------------------------------------------------------------------
  1946.  
  1947. void var::null(int index)
  1948. {
  1949.     if (index >= data_str_len) {
  1950.     cerr << "WARNING: " << " - var::null(" << index << ") - the index out of range." << endl;
  1951.     (*this)[index] = 0;
  1952.     data_str_end = index;
  1953.     }
  1954.     else {
  1955.     data_str[index] = 0;
  1956.     data_str_end = index;
  1957.     }
  1958. }
  1959.  
  1960.  
  1961. void var::changesize(int newsize)
  1962. {
  1963.     if (newsize > data_str_len) {
  1964.     char *buf = new char[newsize];
  1965.     if (data_str) {
  1966.         strncpy(buf, data_str, data_str_end);
  1967.         buf[data_str_end] = 0;
  1968.         delete data_str;
  1969.     }
  1970.     else {
  1971.         *buf = 0;
  1972.         data_str_end = 0;
  1973.     }
  1974.     data_str_len = newsize;
  1975.     data_str = buf;
  1976.     }
  1977. }
  1978.  
  1979.  
  1980. int var::length(void) const
  1981. {
  1982.     return data_str_end;
  1983. }
  1984.  
  1985.  
  1986. const char * var::vartype(void) const
  1987. {
  1988.     switch (is_numeric) {
  1989.     case VAR_STRING:
  1990.         return "VAR_STRING";
  1991.     case VAR_LONG:
  1992.         return "VAR_LONG";
  1993.     case VAR_DOUBLE:
  1994.         return "VAR_DOUBLE";
  1995.     }
  1996.     return "var type unknown";
  1997. }
  1998.  
  1999.  
  2000. void var::change_type(const char *ntype)
  2001. {
  2002.     if (ntype == NULL) {
  2003.     return;
  2004.     }
  2005.     int index = strlen(ntype);
  2006.     if (!index) {
  2007.     return;
  2008.     }
  2009.     char *new_type = new char[index + 1];
  2010.     if (ntype[0] == '(' && ntype[index - 1] == ')') {
  2011.     strcpy(new_type, &ntype[1]);
  2012.     index = strlen(new_type) - 1;
  2013.     if (index <= 0) {
  2014.         delete new_type;
  2015.         return;
  2016.     }
  2017.     new_type[index] = 0;            // drop parens
  2018.     }
  2019.     else {
  2020.     strcpy(new_type, ntype);
  2021.     }
  2022.     if (new_type[index - 1] == ' ') {
  2023.     new_type[index - 1] = 0;
  2024.     }
  2025.     fixed = 1;
  2026.     if (!strcmp(new_type, "var")) {
  2027.     is_numeric = numcheck((const char *) *this);
  2028.     }
  2029.     else if (!strcmp(new_type, "string")) {
  2030.     is_numeric = VAR_STRING;
  2031.     }
  2032.     else if (!strcmp(new_type, "short")) {
  2033.     is_numeric = VAR_LONG;
  2034.     }
  2035.     else if (!strcmp(new_type, "unsigned short")) {
  2036.     is_numeric = VAR_LONG;
  2037.     }
  2038.     else if (!strcmp(new_type, "int")) {
  2039.     is_numeric = VAR_LONG;
  2040.     }
  2041.     else if (!strcmp(new_type, "unsigned int")) {
  2042.     is_numeric = VAR_LONG;
  2043.     }
  2044.     else if (!strcmp(new_type, "long")) {
  2045.     is_numeric = VAR_LONG;
  2046.     }
  2047.     else if (!strcmp(new_type, "unsigned long")) {
  2048.     is_numeric = VAR_LONG;
  2049.     }
  2050.     else if (!strcmp(new_type, "float")) {
  2051.     is_numeric = VAR_DOUBLE;
  2052.     }
  2053.     else if (!strcmp(new_type, "double")) {
  2054.     is_numeric = VAR_DOUBLE;
  2055.     }
  2056.     else {
  2057.     cerr << "WARNING: " << " - change_type(" << new_type << ") - unrecognized type name." << endl;
  2058.     }
  2059.     delete new_type;
  2060. }
  2061.  
  2062.  
  2063. int var::is_string(void) const
  2064. {
  2065.     return is_numeric == VAR_STRING;
  2066. }
  2067.  
  2068.  
  2069. int var::is_double(void) const
  2070. {
  2071.     return is_numeric == VAR_DOUBLE;
  2072. }
  2073.  
  2074.  
  2075. int var::is_long(void) const
  2076. {
  2077.     return is_numeric == VAR_LONG;
  2078. }
  2079.  
  2080.  
  2081. int var::strchr(const char ch) const
  2082. {
  2083.     for (int i = 0; i < data_str_end; ++i) {
  2084.     if (data_str[i] == ch) {
  2085.         return i;
  2086.     }
  2087.     }
  2088.     return -1;
  2089. }
  2090.  
  2091.  
  2092. int var::strrchr(const char ch) const
  2093. {
  2094.     for (int i = data_str_end - 1; i >= 0; --i) {
  2095.     if (data_str[i] == ch) {
  2096.         return i;
  2097.     }
  2098.     }
  2099.     return -1;
  2100. }
  2101.  
  2102.  
  2103. var & var::concat(const var & str)
  2104. {
  2105.     // concatenate strings
  2106.     int new_data_str_end = data_str_end + str.data_str_end;
  2107.     if (new_data_str_end >= data_str_len) {
  2108.     var add;
  2109.     add.data_str_len = data_str_len + str.data_str_len + VAR_PAD_SIZE;
  2110.     add.data_str_end = new_data_str_end;
  2111.     add.data_str = new char[add.data_str_len];
  2112.     strcpy(add.data_str, data_str);
  2113.     strcpy((add.data_str) + data_str_end, str.data_str);
  2114.     *this = add;
  2115.     }
  2116.     else {
  2117.     strcpy(data_str + data_str_end, str.data_str);
  2118.     data_str_end += str.data_str_end;
  2119.     }
  2120.     return *this;
  2121. }
  2122.  
  2123.  
  2124. var & var::format(const char * fmt)
  2125. {
  2126.     if (format_str
  2127.     && format_str != DEFAULT_STRING_FORMAT
  2128.     && format_str != DEFAULT_INT_FORMAT
  2129.     && format_str != DEFAULT_UINT_FORMAT
  2130.     && format_str != DEFAULT_LONG_FORMAT
  2131.     && format_str != DEFAULT_ULONG_FORMAT
  2132.     && format_str != DEFAULT_DOUBLE_FORMAT) {
  2133.         delete format_str;
  2134.     }
  2135.     if (fmt) {
  2136.     format_str = new char[strlen(fmt) + 1];
  2137.     strcpy(format_str, fmt);
  2138.     }
  2139.     else {
  2140.     format_str = NULL;
  2141.     }
  2142.     return *this;
  2143. }
  2144.  
  2145.  
  2146. int var::numcheck(const char * str) const
  2147. {
  2148.     if (!str || !*str) {
  2149.     return VAR_STRING;        // assume a string
  2150.     }
  2151.     char *ptr = (char *) str;
  2152.     int nc = VAR_LONG;            // assume a signed long
  2153.     int decimal_yet = 0;
  2154.     if (*ptr == '.' && *(ptr + 1)) {
  2155.     nc = VAR_DOUBLE;        // floating point number
  2156.     decimal_yet = 1;
  2157.     ++ptr;
  2158.     }
  2159.     else if (*ptr == '-' && *(ptr + 1)) {
  2160.     // skip optional sign char
  2161.     ++ptr;
  2162.     }
  2163.     while (*ptr) {
  2164.     if (*ptr == '.' && !decimal_yet) {
  2165.         decimal_yet = 1;
  2166.         nc = VAR_DOUBLE;        // assume a double
  2167.     }
  2168.     else if (!isdigit(*ptr)) {
  2169.         return VAR_STRING;        // nope.. got a string
  2170.     }
  2171.     ++ptr;
  2172.     }
  2173.     return nc;
  2174. }
  2175.  
  2176. // -----------------------------------------------------------------------------
  2177.  
  2178. int var::save_it(const int save_flag)
  2179. {
  2180.     int s = var::save_me;
  2181.     var::save_me = save_flag;
  2182.     return s;
  2183. }
  2184.  
  2185. // -----------------------------------------------------------------------------
  2186.  
  2187. ostream & operator << (ostream &out, const var &d)
  2188. {
  2189.     d.print(out);
  2190.     return out;
  2191. }
  2192.  
  2193.  
  2194. void var::print(ostream &out) const
  2195. {
  2196.     // NOTE: the "read()" function requires a newline to appear after the last quote.
  2197.     // I assume that this newline was appropriately output by the var class user.
  2198.     if (!format_str || (format_str && *format_str == 0)) {
  2199.     out << "var OBJECT: {"
  2200.         << Inc << "fixed        = " << fixed
  2201.         << Tab << "is_numeric   = " << is_numeric
  2202.         << Tab << "data_str_len = " << data_str_len
  2203.         << Tab << "data_str_end = " << data_str_end
  2204.         << Tab << "data_str     = '" << data_str << "'"
  2205.         << Tab << "format_str   = '" << format_str << "'"
  2206.         << Dec << "}" << endl;
  2207.     }
  2208.     else {
  2209.     // we need to use the specified format string for output
  2210.     int len = length() + 1;
  2211.     char *outbuf = new char[2048];
  2212.     char *fptr = format_str;
  2213.     while (*fptr) {
  2214.         if (*fptr != '%' && *fptr != '\\') {
  2215.         out << *fptr;
  2216.         ++fptr;
  2217.         }
  2218.         else if (*fptr == '\\') {
  2219.         switch (*(fptr + 1)) {
  2220.             case 'n':
  2221.             cout << '\n';
  2222.             break;
  2223.             case 't':
  2224.             cout << '\t';
  2225.             break;
  2226.             case 'v':
  2227.             cout << '\v';
  2228.             break;
  2229.             case 'b':
  2230.             cout << '\b';
  2231.             break;
  2232.             case 'r':
  2233.             cout << '\r';
  2234.             break;
  2235.             case 'f':
  2236.             cout << '\f';
  2237.             break;
  2238.             case 'a':
  2239.             cout << '\007';
  2240.             break;
  2241.             case '\\':
  2242.             cout << '\\';
  2243.             break;
  2244.             case '?':
  2245.             cout << '\?';
  2246.             break;
  2247.             case '\'':
  2248.             cout << '\'';
  2249.             break;
  2250.             case '\"':
  2251.             cout << '\"';
  2252.             break;
  2253.             default:
  2254.             cout << *(fptr + 1);
  2255.         }
  2256.         fptr += 2;
  2257.         }
  2258.         else {
  2259.         // Hmmm.. we need to do some special formatting
  2260.         // first extract this printf-style format string
  2261.         char smallfmtstr[128];
  2262.         char *smptr = smallfmtstr;
  2263.         *smptr = 0;
  2264.         if (*(fptr + 1) == '%') {
  2265.             strcpy(outbuf, "%");
  2266.             fptr += 2;
  2267.         }
  2268.         else {
  2269.             while (*fptr) {
  2270.             *smptr = *fptr++;
  2271.             *(smptr + 1) = 0;
  2272.             // integer
  2273.             if (*smptr == 'd') {
  2274.                 sprintf(outbuf, smallfmtstr, (int) *this);
  2275.                 break;
  2276.             }
  2277.             // unsigned integer
  2278.             if (*smptr == 'o' || *smptr == 'u' || *smptr == 'x' || *smptr == 'X') {
  2279.                 sprintf(outbuf, smallfmtstr, (unsigned int) *this);
  2280.                 break;
  2281.             }
  2282.             // float or double
  2283.             if (*smptr == 'f' || *smptr == 'e' || *smptr == 'E' || *smptr == 'g' || *smptr == 'G') {
  2284.                 sprintf(outbuf, smallfmtstr, (double) *this);
  2285.                 break;
  2286.             }
  2287.             // character
  2288.             if (*smptr == 'c') {
  2289.                 if (!strcmp(vartype(), "VAR_STRING")) {
  2290.                 const char *tmp = (const char *) (*this);
  2291.                 sprintf(outbuf, smallfmtstr, tmp[0]);
  2292.                 }
  2293.                 else {
  2294.                 sprintf(outbuf, smallfmtstr, (char) ((int) *this));
  2295.                 }
  2296.                 break;
  2297.             }
  2298.             // string
  2299.             if (*smptr == 's') {
  2300.                 sprintf(outbuf, smallfmtstr, (const char *) *this);
  2301.                 break;
  2302.             }
  2303.             ++smptr;
  2304.             }
  2305.         }
  2306.         out << outbuf;
  2307.         }
  2308.     }
  2309.     out << flush;
  2310.     delete outbuf;
  2311.     }
  2312. }
  2313.  
  2314.  
  2315. istream & operator >> (istream &in, var &d)
  2316. {
  2317.     d.read(in);
  2318.     return in;
  2319. }
  2320.  
  2321.  
  2322. void var::read(istream &in)
  2323. {
  2324.     // input the same format as was created by the output operator
  2325.     char buf1[4096];
  2326.     char buf2[4096];
  2327.     if (!format_str || (format_str && *format_str == 0)) {
  2328.     look_for(in, '{');
  2329.     look_for(in, '=');
  2330.     in >> fixed;
  2331.     look_for(in, '=');
  2332.     in >> is_numeric;
  2333.     look_for(in, '=');
  2334.     in >> data_str_len;
  2335.     look_for(in, '=');
  2336.     in >> data_str_end;
  2337.     look_for(in, '=');
  2338.     scan_string(in, buf1, sizeof(buf1));
  2339.     look_for(in, '=');
  2340.     scan_string(in, buf2, sizeof(buf2));
  2341.     look_for(in, '}');
  2342.     *this = buf1;
  2343.     format(buf2);
  2344.     }
  2345.     else {
  2346.     // LEE: need to add input/output formatting capabilities
  2347.     }
  2348. }
  2349.  
  2350. @//E*O*F var.C//
  2351. chmod u=rw,g=r,o=r var.C
  2352.  
  2353. echo x - Misc.H
  2354. sed 's/^@//' > "Misc.H" <<'@//E*O*F Misc.H//'
  2355. // 
  2356. // NAME:    MISC.H
  2357. //
  2358. // PURPOSE:    generalized functions for C++ class library routines
  2359. // AUTHOR:    Lee Hounshell
  2360. //
  2361.  
  2362. #ifndef MISC_H
  2363. #define MISC_H
  2364.  
  2365. #include <stream.h>
  2366.  
  2367.     char *itoa(const int foo);
  2368.     char *uitoa(const unsigned int foo);
  2369.  
  2370. #ifdef HP
  2371.     char *ltoa(long foo);
  2372.     char *ultoa(unsigned long foo);
  2373. #else
  2374.     char *ltoa(const long foo);
  2375.     char *ultoa(const unsigned long foo);
  2376. #endif
  2377.  
  2378.     char *dtoa(const double foo);
  2379.     double atod(char * foo);
  2380.     char *ltoTime(const long date24);
  2381.     istream & look_for(istream &in, char c);
  2382.     void scan_string(istream &in, char *ptr, int size);
  2383.     ostream & Tab(ostream &out);
  2384.     ostream & Inc(ostream &out);
  2385.     ostream & Dec(ostream &out);
  2386.  
  2387. #endif
  2388.  
  2389. @//E*O*F Misc.H//
  2390. chmod u=rw,g=r,o=r Misc.H
  2391.  
  2392. echo x - Misc.C
  2393. sed 's/^@//' > "Misc.C" <<'@//E*O*F Misc.C//'
  2394. // 
  2395. // NAME:    MISC.C
  2396. //
  2397. // PURPOSE:    generalized functions for C++ class library routines
  2398. // AUTHOR:    Lee Hounshell
  2399. //
  2400.  
  2401. #include <stdlib.h>
  2402. #include <stream.h>
  2403. #include <memory.h>
  2404. #include <string.h>
  2405. #include <ctype.h>
  2406. #include "Misc.H"
  2407.  
  2408.  
  2409. // =============================================================================
  2410. // stuff thet jes' be here 'cause i wuz be 2 lazy 2 done drop it sumplace else, Mazza!
  2411. // =============================================================================
  2412.  
  2413.  
  2414. // -----------------------------------------------------------------------------
  2415. // convert an integer into an ascii string.  return a pointer to that string.
  2416. //
  2417. char *itoa(const int foo)
  2418. {
  2419.     static char int_buf[28];
  2420.     sprintf(int_buf, "%d", foo);
  2421.     return int_buf;
  2422. }
  2423.  
  2424.  
  2425. // convert an unsigned integer into an ascii string.  return a pointer to that string.
  2426. //
  2427. char *uitoa(const unsigned int foo)
  2428. {
  2429.     static char int_buf[28];
  2430.     sprintf(int_buf, "%u", foo);
  2431.     return int_buf;
  2432. }
  2433.  
  2434.  
  2435. // convert a long into an ascii string.  return a pointer to that string.
  2436. //
  2437. #ifdef HP
  2438. char *ltoa(long foo)
  2439. #else
  2440. char *ltoa(const long foo)
  2441. #endif
  2442. {
  2443.     static char long_buf[28];
  2444.     sprintf(long_buf, "%ld", foo);
  2445.     return long_buf;
  2446. }
  2447.  
  2448.  
  2449. // convert an unsigned long into an ascii string.  return a pointer to that string.
  2450. //
  2451. #ifdef HP
  2452. char *ultoa(unsigned long foo)
  2453. #else
  2454. char *ultoa(const unsigned long foo)
  2455. #endif
  2456. {
  2457.     static char long_buf[28];
  2458.     sprintf(long_buf, "%lu", foo);
  2459.     return long_buf;
  2460. }
  2461.  
  2462.  
  2463. // convert a double into an ascii string.  return a pointer to that string.
  2464. // truncate any extra zeros after the decimal point.
  2465. //
  2466. char *dtoa(const double foo)
  2467. {
  2468.     static char double_buf[28];
  2469.     sprintf(double_buf, "%lf", foo);
  2470.     char *ptr;
  2471.     for (ptr = double_buf; *ptr; ++ptr) {
  2472.     if (*ptr == '.') {
  2473.         // we may need to truncate zeroes
  2474.         ptr = double_buf + (strlen(double_buf) - 1);
  2475.         while (*ptr == '0') {
  2476.         *ptr-- = 0;
  2477.         }
  2478.         if (*ptr == '.') {
  2479.         *ptr = 0;
  2480.         }
  2481.         break;
  2482.     }
  2483.     }
  2484.     return double_buf;
  2485. }
  2486.  
  2487.  
  2488. // convert an ascii string to a double
  2489. //
  2490. double atod(char * foo)
  2491. {
  2492.     double d = 0;
  2493.     if (!foo || !*foo) {
  2494.     return d;
  2495.     }
  2496.     if (!isdigit(*foo)) {
  2497.     if (*foo != '-' && *foo != '+') {
  2498.         return d;
  2499.     }
  2500.     if (!isdigit(*(foo + 1))) {
  2501.         return d;
  2502.     }
  2503.     }
  2504.     sscanf(foo, "%lf", &d);
  2505.     return d;
  2506. }
  2507.  
  2508. // -----------------------------------------------------------------------------
  2509.  
  2510. // convert a 24-hour time (hhmm) into LMOS string format (hhmmZ - where Z is 'A' or 'P')
  2511. //
  2512. char *ltoTime(const long date24)
  2513. {
  2514.     static char time_buf[6];
  2515.     *time_buf = 0;
  2516.     if (date24 != 0L) {
  2517.     long minute = date24 % 100;
  2518.     long hour = (date24 - minute) / 100;
  2519.     char ampm = 'A';
  2520.     if (hour >= 12) {
  2521.         ampm = 'P';
  2522.         if (hour > 12) hour -= 12;
  2523.     }
  2524.     sprintf(time_buf, "%02d%02d%c", hour, minute, ampm);
  2525.     return time_buf;
  2526.     }
  2527. }
  2528.  
  2529.  
  2530. // -----------------------------------------------------------------------------
  2531. // scan input until the desired character is found
  2532. //
  2533. istream & look_for(istream &in, char c)
  2534. {
  2535.     int input = 0;
  2536.     if (getenv("INPUT_DEBUG") != NULL) {
  2537.     cerr << "Debug: looking for input character '" << c << "'" << endl;
  2538.     }
  2539.     while (input != c && input != EOF) {
  2540.     input = in.get();
  2541.     if (getenv("INPUT_DEBUG") != NULL) {
  2542.         cerr << input;
  2543.     }
  2544.     }
  2545.     return in;
  2546. }
  2547.  
  2548.  
  2549. // -----------------------------------------------------------------------------
  2550. // this function is used by lots of other classes for I/O, also.
  2551. // it really is a sort of "general-purpose," non-class-specific routine
  2552. // i use it for extracting class memebers from a saved object
  2553. //
  2554. void scan_string(istream &in, char *ptr, int size)
  2555. {
  2556.     char buffer[3];
  2557.     char *input;
  2558.     if (size) --size;
  2559.     if (getenv("INPUT_DEBUG") != NULL) {
  2560.     cerr << "Debug: scanning for string (length=" << size << ")" << endl;
  2561.     }
  2562.     if (ptr != NULL) {
  2563.     input = ptr;
  2564.     }
  2565.     else {
  2566.     input = buffer;
  2567.     }
  2568.     *input = 0;
  2569.     look_for(in, '\'');                // find first quote
  2570.     int endflag = 0;
  2571.     int count = 0;
  2572.     while (1) {
  2573.     int ch;
  2574.     if ((ch = in.get()) == EOF) {
  2575.         if (getenv("INPUT_DEBUG") != NULL) {
  2576.         cerr << "debug: scan_string(): unexpected EOF found" << endl;
  2577.         }
  2578.         *input = 0;
  2579.         break;
  2580.     }
  2581.     *input = ch;
  2582.     if (getenv("INPUT_DEBUG") != NULL) {
  2583.         cerr << *input;
  2584.     }
  2585.     if (*input == '\n' && endflag) {    // all done!
  2586.         *input = 0;
  2587.         if (getenv("INPUT_DEBUG") != NULL) {
  2588.         cerr << "\nDebug: scan_string() found: '" << ptr << "'" << endl;
  2589.         }
  2590.         break;                // found end of string
  2591.     }
  2592.     if (count >= size) {            // string is too big for buffer
  2593.         if (getenv("INPUT_DEBUG") != NULL) {
  2594.         cerr << "\nDebug: scan_string() size exceeded - truncating string" << endl;
  2595.         }
  2596.         if (ch != '\'') {
  2597.         look_for(in, '\'');        // skip to last quote
  2598.         }
  2599.         endflag = 1;
  2600.         continue;
  2601.     }
  2602.     if (ptr != NULL && endflag) {        // possibly found end of string
  2603.         *(input+1) = *input;
  2604.         *input = '\'';
  2605.         ++input;
  2606.         ++count;
  2607.     }
  2608.     if ((endflag = (*input == '\'')) == 0) {// got a close quote??
  2609.         if (*ptr) ++input;
  2610.         ++count;
  2611.     }
  2612.     }
  2613. }
  2614.  
  2615.  
  2616. // these functions are also used by other classes for I/O.
  2617. // they keep track of "indent" levels for printing objects with inheritance
  2618.  
  2619. static int no_tab_stops = 0;
  2620.  
  2621.  
  2622. // -----------------------------------------------------------------------------
  2623. //
  2624. ostream & Tab(ostream &out)
  2625. {
  2626.     out << "\n";
  2627.     for (int i = 0; i < no_tab_stops; ++i) {
  2628.     out << "    ";                // really one-half a tab stop
  2629.     }
  2630.     return out;
  2631. }
  2632.  
  2633.  
  2634. // -----------------------------------------------------------------------------
  2635. //
  2636. ostream & Inc(ostream &out)
  2637. {
  2638.     ++no_tab_stops;
  2639.     return Tab(out);
  2640. }
  2641.  
  2642.  
  2643. // -----------------------------------------------------------------------------
  2644. //
  2645. ostream & Dec(ostream &out)
  2646. {
  2647.     --no_tab_stops;
  2648.     return Tab(out);
  2649. }
  2650.  
  2651. @//E*O*F Misc.C//
  2652. chmod u=rw,g=r,o=r Misc.C
  2653.  
  2654. echo x - demo.C
  2655. sed 's/^@//' > "demo.C" <<'@//E*O*F demo.C//'
  2656. #include    <stdlib.h>
  2657. #include    <stream.h>
  2658. #include    <var.H>
  2659.  
  2660. main ()
  2661. {
  2662.     var value;                // declare an "untyped" var
  2663.     value = "hello world";            // initialize it
  2664.     cout << value << endl;            // output "hello world"
  2665.     value = value(3, value.length() - 6);    // substring example
  2666.     cout << value << endl;            // output "lo wo"
  2667.     value = 35;                // assignment of int
  2668.     value += 42.375;            // add 42.375 to present value
  2669.     cout << value << endl;            // output "77.375"
  2670.     cout << value.format("formatted output example %05d of value") << endl;
  2671.     cout << value.format("multiple outputs #1=%d, #2=%9.2f of value") << endl;
  2672.     value.null(2);                // truncate string
  2673.     value += " sunset strip";        // concatenate a string
  2674.     cout << value.format("%s") << endl;    // output "77 sunset strip"
  2675.     cout << value[3] << value[4] << value[5] << endl; // output "sun"
  2676. }
  2677.  
  2678. @//E*O*F demo.C//
  2679. chmod u=rw,g=r,o=r demo.C
  2680.  
  2681. exit 0
  2682. -- 
  2683. Lee Hounshell - (510) 823-2432
  2684. tlhouns@srv.pacbell.com
  2685. Alchemical Engineer and Virtual Realist
  2686.