home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume33 / var / part01 < prev    next >
Encoding:
Text File  |  1992-11-28  |  54.4 KB  |  2,185 lines

  1. Newsgroups: comp.sources.misc
  2. From: tlhouns@srv.pacbell.com (Lee Hounshell)
  3. Subject:  v33i127:  var - C++ class library "var" (v1.1) and "VarMap" (associative arrays), Part01/02
  4. Message-ID: <csm-v33i127=var.155557@sparky.IMD.Sterling.COM>
  5. X-Md4-Signature: 1694cd4714b8b4ce309b6b33452adcd2
  6. Date: Wed, 25 Nov 1992 21:56:33 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: tlhouns@srv.pacbell.com (Lee Hounshell)
  10. Posting-number: Volume 33, Issue 127
  11. Archive-name: var/part01
  12. Environment: C++, G++
  13. Supersedes: var: Volume 31, Issue 91-92
  14.  
  15. This is the latest release of "var", and "VarMap".
  16. This is a C++ object library that provides a "super-string" class with
  17. "associative array" capabilities.
  18.  
  19. The var class does a pretty good job of offering a data object that assumes
  20. its "type" at run time, based on context of use.  Rarely will you need to
  21. declare int's, or longs, or doubles or char[] or even string objects!
  22. "Var" does it all (or at least tries to).
  23.  
  24.     + var will do base data types (eg: int, long, char *, float, string ...)
  25.     + var will do arithmetic
  26.     + var will do strings and operations on strings
  27.     + var will do sub-strings and operations on sub-strings
  28.     + var will intelligently "mix" operations between mixed types
  29.     + var will do formatted output using the stream library
  30.     + individual vars can be "staticly" typed, or they can assume
  31.       type at runtime, based on context.
  32.     + VarMap will do associative arrays of vars indexed by vars.
  33.  
  34. To use this class, simply type make and a library file "libvar.a" will be
  35. created.  This class has been used extensively here at Pacific Bell as a
  36. base class in development of our own internal C++ class libraries. I've
  37. even used "var" as the YYSTYPE type inside yacc/lex programs!!
  38.  
  39. To try out the enclosed demo programs, type "make demo".
  40.  
  41. Both var and VarMap have been tested and used on the following architectures:
  42.  
  43.     - Sun C++ versions 2.0 and 2.1
  44.     - AT&T C++ versions 2.0 and 2.1
  45.     - g++ (yes, I now support GNU C++!!)
  46.  
  47. If you like (or dislike) var and/or VarMap, please drop me a line.
  48. Mail bug reports and comments to:
  49. tlhouns@srv.pacbell.com
  50.  
  51. -Lee
  52. --------
  53. #! /bin/sh
  54. # This is a shell archive.  Remove anything before this line, then feed it
  55. # into a shell via "sh file" or similar.  To overwrite existing files,
  56. # type "sh file -c".
  57. # Contents:  README demo2.C var.3++ var.C
  58. # Wrapped by kent@sparky on Tue Nov 24 09:31:37 1992
  59. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  60. echo If this archive is complete, you will see the following message:
  61. echo '          "shar: End of archive 1 (of 2)."'
  62. if test -f 'README' -a "${1}" != "-c" ; then 
  63.   echo shar: Will not clobber existing file \"'README'\"
  64. else
  65.   echo shar: Extracting \"'README'\" \(1566 characters\)
  66.   sed "s/^X//" >'README' <<'END_OF_FILE'
  67. X
  68. XThis is the latest release of "var", and "VarMap".
  69. XThis is a C++ object library that provides a "super-string" class with
  70. X"associative array" capabilities.
  71. X
  72. XThe var class does a pretty good job of offering a data object that assumes
  73. Xits "type" at run time, based on context of use.  Rarely will you need to
  74. Xdeclare int's, or longs, or doubles or char[] or even string objects!
  75. X"Var" does it all (or at least tries to).
  76. X
  77. X    + var will do base data types (eg: int, long, char *, float, string ...)
  78. X    + var will do arithmetic
  79. X    + var will do strings and operations on strings
  80. X    + var will do sub-strings and operations on sub-strings
  81. X    + var will intelligently "mix" operations between mixed types
  82. X    + var will do formatted output using the stream library
  83. X    + individual vars can be "staticly" typed, or they can assume
  84. X      type at runtime, based on context.
  85. X    + VarMap will do associative arrays of vars indexed by vars.
  86. X
  87. XTo use this class, simply type make and a library file "libvar.a" will be
  88. Xcreated.  This class has been used extensively here at Pacific Bell as a
  89. Xbase class in development of our own internal C++ class libraries. I've
  90. Xeven used "var" as the YYSTYPE type inside yacc/lex programs!!
  91. X
  92. XTo try out the enclosed demo programs, type "make demo".
  93. X
  94. XBoth var and VarMap have been tested and used on the following architectures:
  95. X
  96. X    - Sun C++ versions 2.0 and 2.1
  97. X    - AT&T C++ versions 2.0 and 2.1
  98. X    - g++ (yes, I now support GNU C++!!)
  99. X
  100. XIf you like (or dislike) var and/or VarMap, please drop me a line.
  101. XMail bug reports and comments to:
  102. Xtlhouns@srv.pacbell.com
  103. X
  104. X-Lee
  105. END_OF_FILE
  106.   if test 1566 -ne `wc -c <'README'`; then
  107.     echo shar: \"'README'\" unpacked with wrong size!
  108.   fi
  109.   # end of 'README'
  110. fi
  111. if test -f 'demo2.C' -a "${1}" != "-c" ; then 
  112.   echo shar: Will not clobber existing file \"'demo2.C'\"
  113. else
  114.   echo shar: Extracting \"'demo2.C'\" \(362 characters\)
  115.   sed "s/^X//" >'demo2.C' <<'END_OF_FILE'
  116. X#include    <VarMap.H>
  117. X
  118. Xmain ()
  119. X{
  120. X    VarMap aa;                // declare a VarMap
  121. X    var lee = "foobar";
  122. X    if (!aa.element(lee)) {
  123. X    aa[lee] = "hello world";    // create/assign using index "foobar"
  124. X    }
  125. X    aa[42] = "testing 123";        // create/assign using index "42"
  126. X    aa[5] = 123.45;            // create/assign using index "5"
  127. X    aa.display();            // display this map to stderr
  128. X}
  129. X
  130. END_OF_FILE
  131.   if test 362 -ne `wc -c <'demo2.C'`; then
  132.     echo shar: \"'demo2.C'\" unpacked with wrong size!
  133.   fi
  134.   # end of 'demo2.C'
  135. fi
  136. if test -f 'var.3++' -a "${1}" != "-c" ; then 
  137.   echo shar: Will not clobber existing file \"'var.3++'\"
  138. else
  139.   echo shar: Extracting \"'var.3++'\" \(15362 characters\)
  140.   sed "s/^X//" >'var.3++' <<'END_OF_FILE'
  141. X.po 6
  142. X.TH VAR 3++ "1/92" "Version 1.1" "Variable Base Type String Class Library"
  143. X
  144. X.SH CLASS
  145. XVAR    \- Variable Base Type String Class Library
  146. X.SH SYNOPSIS
  147. X.B #include     <var.H>
  148. X.PP
  149. X.nf
  150. X.ta.5i 1.0i 4.0i
  151. X\fB
  152. Xclass var {
  153. X
  154. X  public:
  155. X    // Constructors & Destructors
  156. X    var(void);                    // constructor
  157. X    var(const varsize &);            // constructor
  158. X    var(const char *);                // constructor
  159. X    var(const char);                // constructor
  160. X    var(const short);                // constructor
  161. X    var(const unsigned short);            // constructor
  162. X    var(const int);                // constructor
  163. X    var(const unsigned int);            // constructor
  164. X    var(const long);                // constructor
  165. X    var(const unsigned long);            // constructor
  166. X    var(const double);                // constructor
  167. X    var(const var &);                // copy constructor
  168. X    ~var(void);                    // destructor
  169. X
  170. X    // Operators
  171. X    var & operator = (const char *);        // assignment
  172. X    var & operator = (const var &);        // assignment
  173. X    char & operator [] (const int);        // indexing
  174. X    subvar & operator () (int, int) const;    // substring
  175. X    subvar & operator () (const int) const;    // substring
  176. X    friend ostream & operator << (ostream &, const var &); // output
  177. X    friend class subvar;            // substring
  178. X
  179. X    // More Operators (used for arithmetic type extension)
  180. X    var & operator = (const char);        // assignment
  181. X    var & operator = (const short);        // assignment
  182. X    var & operator = (const unsigned short);    // assignment
  183. X    var & operator = (const int);        // assignment
  184. X    var & operator = (const unsigned int);    // assignment
  185. X    var & operator = (const long);        // assignment
  186. X    var & operator = (const unsigned long);    // assignment
  187. X    var & operator = (const double);        // assignment
  188. X
  189. X    // Casting Operators
  190. X    operator char * (void) const;        // type conversion
  191. X    operator double (void) const;        // type conversion
  192. X
  193. X    // Assignment Operators
  194. X    var & operator ++ (void);            // increment (pre-index only)
  195. X    var & operator -- (void);            // decrement (pre-index only)
  196. X    var operator ! (void) const;        // not
  197. X
  198. X    var operator + (const var &) const;        // addition OR concatenation
  199. X    var operator - (const var &) const;        // subtraction
  200. X    var operator * (const var &) const;        // multiplication
  201. X    var operator / (const var &) const;        // division
  202. X    var operator % (const var &) const;        // remainder
  203. X
  204. X    var & operator += (const var &);        // addition OR concatenation
  205. X    var & operator -= (const var &);        // subtraction
  206. X    var & operator *= (const var &);        // multiplication
  207. X    var & operator /= (const var &);        // division
  208. X    var & operator %= (const var &);        // remainder
  209. X
  210. X    var & operator += (const char &);        // addition OR concatenation
  211. X    var & operator += (const char *);        // addition OR concatenation
  212. X    var & operator -= (const char *);        // subtraction
  213. X    var & operator *= (const char *);        // multiplication
  214. X    var & operator /= (const char *);        // division
  215. X    var & operator %= (const char *);        // remainder
  216. X
  217. X    var & operator += (const double);        // addition OR concatenation
  218. X    var & operator -= (const double);        // subtraction
  219. X    var & operator *= (const double);        // multiplication
  220. X    var & operator /= (const double);        // division
  221. X    var & operator %= (const double);        // remainder
  222. X
  223. X    friend var operator + (const char *, const var &); // addition OR concatenation
  224. X    friend var operator - (const char *, const var &); // subtraction
  225. X    friend var operator * (const char *, const var &); // multiplication
  226. X    friend var operator / (const char *, const var &); // division
  227. X    friend var operator % (const char *, const var &); // remainder
  228. X    friend var operator + (const var &, const char *); // addition OR concatenation
  229. X    friend var operator - (const var &, const char *); // subtraction
  230. X    friend var operator * (const var &, const char *); // multiplication
  231. X    friend var operator / (const var &, const char *); // division
  232. X    friend var operator % (const var &, const char *); // remainder
  233. X
  234. X    friend var operator + (const var &, const double); // addition OR concatenation
  235. X    friend var operator - (const var &, const double); // subtraction
  236. X    friend var operator * (const var &, const double); // multiplication
  237. X    friend var operator / (const var &, const double); // division
  238. X    friend var operator % (const var &, const double); // remainder
  239. X    friend var operator + (const double, const var &); // addition OR concatenation
  240. X    friend var operator - (const double, const var &); // subtraction
  241. X    friend var operator * (const double, const var &); // multiplication
  242. X    friend var operator / (const double, const var &); // division
  243. X    friend var operator % (const double, const var &); // remainder
  244. X
  245. X    // Equality Operators
  246. X    int operator == (const var &) const;    // equality
  247. X    int operator != (const var &) const;    // inequality
  248. X    int operator < (const var &) const;        // less than
  249. X    int operator > (const var &) const;        // greater than
  250. X    int operator <= (const var &) const;    // less than or equal
  251. X    int operator >= (const var &) const;    // greater than or equal
  252. X
  253. X    friend int operator == (const var &, const char *); // equality
  254. X    friend int operator != (const var &, const char *); // inequality
  255. X    friend int operator < (const var &, const char *);  // less than
  256. X    friend int operator > (const var &, const char *);  // greater than
  257. X    friend int operator <= (const var &, const char *); // less than or equal
  258. X    friend int operator >= (const var &, const char *); // greater than or equal
  259. X    friend int operator == (const char *, const var &); // equality
  260. X    friend int operator != (const char *, const var &); // inequality
  261. X    friend int operator < (const char *, const var &);  // less than
  262. X    friend int operator > (const char *, const var &);  // greater than
  263. X    friend int operator <= (const char *, const var &); // less than or equal
  264. X    friend int operator >= (const char *, const var &); // greater than or equal
  265. X
  266. X    friend int operator == (const var &, const double); // equality
  267. X    friend int operator != (const var &, const double); // inequality
  268. X    friend int operator < (const var &, const double);  // less than
  269. X    friend int operator > (const var &, const double);  // greater than
  270. X    friend int operator <= (const var &, const double); // less than or equal
  271. X    friend int operator >= (const var &, const double); // greater than or equal
  272. X    friend int operator == (const double, const var &); // equality
  273. X    friend int operator != (const double, const var &); // inequality
  274. X    friend int operator < (const double, const var &);  // less than
  275. X    friend int operator > (const double, const var &);  // greater than
  276. X    friend int operator <= (const double, const var &); // less than or equal
  277. X    friend int operator >= (const double, const var &); // greater than or equal
  278. X
  279. X    // Custom Interface
  280. X    void null(int);                // "null" out string
  281. X    void changesize(int);            // change allocated memory
  282. X    int length(void) const;            // length of string
  283. X    const char * vartype(void) const;        // name of this var type
  284. X    void change_type(const char *);        // change var type
  285. X    int is_string(void) const;            // test var type
  286. X    int is_double(void) const;            // test var type
  287. X    int is_long(void) const;            // test var type
  288. X    int strchr(const char) const;        // strchr(char) index
  289. X    int strrchr(const char) const;        // strrchr(char) index
  290. X    var & concat(const var &);            // concatenation
  291. X    var & format(const char *);            // set output format
  292. X};
  293. X.fi
  294. X\fP
  295. X
  296. X.SH DESCRIPTION
  297. XClass \fBvar\fP represents a \fBstring\fP object class that also provides all
  298. Xthe traditional functionality of the C base types: char, int, long, float, double, and char*.
  299. X\fBVar\fP, is in many ways a "super-string" class.
  300. XThe var class does a pretty good job of offering a base data "container" object that can either
  301. Xassume its "type" at run time, based on context or remain a "fixed" type, always.
  302. X
  303. X.SS var will do
  304. X.TP 2
  305. X+
  306. Xall the base data types (eg: short, int, long, char *, float, double ...)
  307. X.TP 2
  308. X+
  309. Xstring types
  310. X.TP 2
  311. X+
  312. Xarithmetic
  313. X.TP 2
  314. X+
  315. Xstrings and operations on strings
  316. X.TP 2
  317. X+
  318. Xsub-strings and operations on sub-strings
  319. X.TP 2
  320. X+
  321. Xintelligent "mixing" of operations between mixed types
  322. X.TP 2
  323. X+
  324. Xformatted output using the stream library
  325. X
  326. X.SH PUBLIC CONSTRUCTORS
  327. X.SS var(void);
  328. XThis constructor is used to declare an "untyped" var object.  Type is determined
  329. Xat run-time, based on context of use.
  330. X
  331. X.SS var(const varsize &);
  332. XThis constructor is used to declare an "string" var object, with preallocated memory.
  333. XThe object's type can change at run-time, based on context.
  334. X
  335. X.SS var(const char *);
  336. XThis constructor is used to declare a "string" object initialize from a "char *".
  337. XThe object's type can change at run-time, based on context.
  338. X
  339. X.SS var(const char);
  340. XThis constructor is used to declare an "numeric" var object, initialized from a char.
  341. XThe object's type can change at run-time, based on context.
  342. X
  343. X.SS var(const short);
  344. XThis constructor is used to declare an "numeric" var object, initialized from a short.
  345. XThe object's type is fixed and will not change at run-time.
  346. X
  347. X.SS var(const unsigned short);
  348. XThis constructor is used to declare an "numeric" var object, initialized from an unsigned short.
  349. XThe object's type is fixed and will not change at run-time.
  350. X
  351. X.SS var(const int);
  352. XThis constructor is used to declare an "numeric" var object, initialized from an int.
  353. XThe object's type is fixed and will not change at run-time.
  354. X
  355. X.SS var(const unsigned int);
  356. XThis constructor is used to declare an "numeric" var object, initialized from an unsigned int.
  357. XThe object's type is fixed and will not change at run-time.
  358. X
  359. X.SS var(const long);
  360. XThis constructor is used to declare an "numeric" var object, initialized from a long.
  361. XThe object's type is fixed and will not change at run-time.
  362. X
  363. X.SS var(const unsigned long);
  364. XThis constructor is used to declare an "numeric" var object, initialized from an unsigned long.
  365. XThe object's type is fixed and will not change at run-time.
  366. X
  367. X.SS var(const double);
  368. XThis constructor is used to declare an "numeric" var object, initialized from a double or float.
  369. XThe object's type is fixed and will not change at run-time.
  370. X
  371. X.SS var(const var &);
  372. XThis constructor is used to declare a var object, which is a copy of another var.
  373. XThe object assumes the characteristics of the initializing object.
  374. X
  375. X.SS ~var(void);
  376. XThe destructor returns all memory allocated by the object back to the OS.
  377. X
  378. X
  379. X.SH PUBLIC OPERATORS
  380. X.SS Arithmetic and Concatenation Operators
  381. XMost operators (+, -, /, *, %, +=, etc..) will operate as expected.
  382. XThe "+" and "+=" operators will either do addition or concatenation, as appropriate.
  383. Xif concatenation is required, then the \fB"var.concat(var)"\fP member function should
  384. Xbe used.
  385. X
  386. X.SS Relational Operators
  387. XThese also operate as expected.  If "string" objects are compared, the comparison
  388. Xwill be as performed by \fBstrcmp(3)\fP.
  389. X
  390. X.SS The Indexing Operator []
  391. XYou can index a character from inside a \fBvar\fP by using
  392. Xthe \fB"char & operator [] (const int);"\fP operator.
  393. XIf you attempt to index \fBbeyond\fP a \fBvar\fP object's current end, then
  394. Xthe referenced object will be automatically extended (padded with spaces)
  395. Xto the desired length.
  396. XA reference to the character is returned, which can be assigned to.
  397. XDo not assign the NULL character using this operator.
  398. XInstead call the member function \fB"null(index)"\fP.
  399. X
  400. X.SS Sub-strings
  401. XTwo operators are provide for substring operation.  The
  402. Xfirst, \fB"subvar & operator () (int start, int length) const;"\fP
  403. Xwill extract a string starting at "start" for "length" characters.
  404. XThe second, \fB"subvar & operator () (const int start) const;"\fP will
  405. Xextract a string starting at "start" to the end of the string.
  406. X
  407. X.SS Type Casting
  408. XOnly two type casts are required by \fBvar\fP. The first converts
  409. Xthe object into a "char *".  The second converts the object into a
  410. Xdouble.  Implicit conversion between "char *" and "double" types
  411. Xwill be performed by your C++ compiler.
  412. X
  413. X.SS Formatted Output
  414. XYou can use \fBvar\fP with the io stream library.  Objects can be
  415. Xoutput using the ">>" operator.
  416. XFor formatted output, be sure to set the object's "format template"
  417. Xprior to calling the ">>" operator.  (see \fB"var & format(const char *);"\fP)
  418. X
  419. X.SH PUBLIC MEMBER FUNCTIONS
  420. X
  421. X.SS Truncating a string 
  422. XThe \fB"void null(int index);"\fP function will truncate a \fBvar\fP
  423. Xobject, starting from the specified index postion.
  424. X
  425. X.SS Memory Allocation
  426. XThe \fB"void changesize(int newsize);"\fP can be used to increase
  427. Xallocated memory for a var.  Memory can NOT be decreased.  Allocated
  428. Xmemory is returned to the heap when an object goes out of scope.
  429. X
  430. X.SS Determining Var's Length
  431. XThe \fB"int length(void) const;"\fP function returns the "size" of a \fBvar\fP.
  432. X
  433. X.SS Determining Var's Type
  434. XThe \fB"const char * vartype(void) const;"\fP function returns the "type" of a \fBvar\fP.
  435. XPossible types are: "VAR_STRING", "VAR_LONG" and "VAR_DOUBLE".
  436. X
  437. X.SS Explititly Changing a Var's Type
  438. XThe \fB"void change_type(const char *newtype);"\fP function can be used
  439. Xto set an exact type.  Valid values for "newtype" are "string", "short",
  440. X"unsigned short", "int", "unsigned int", "long", "unsigned long",
  441. X"float", and "double".
  442. X
  443. X.SS Testing a Var's Type
  444. XThree functions are provided that allow testing a \fBvar\fP type.
  445. XThey are as follows: \fB"int is_string(void) const;"\fP,
  446. X\fB"int is_double(void) const;"\fP, and \fB"int is_long(void) const;"\fP
  447. X
  448. X.SS Searching for a Character
  449. XTwo functions are provided that search a \fBvar\fP for a specified
  450. Xcharacter.  Both return an offset.  The first \fB"int strchr(const char) const;"\fP
  451. Xsearches forward.  The second, \fB"int strrchr(const char) const;"\fP
  452. Xsearches backward.
  453. X
  454. X.SS Concatenation
  455. XConcatenation can be forced, regardless of type with the \fB"var & concat(const var &);"\fP
  456. Xfunction.
  457. X
  458. X.SS Setting the Output Format
  459. XThe \fB"var & format(const char *fmt);"\fP function will allow you to specify an
  460. Xoutput format.  This format will remain in effect until changed.  Printf()
  461. Xstyle output formats can be introduced anywhere in the format statment.
  462. XMultiple formateed output directives can appear in the same "fmt".  Each
  463. Xdirective will receive a copy of the object.  Automatic type conversion will
  464. Xoccur.
  465. X
  466. X
  467. X.SH AUTHOR
  468. XLee Hounshell - 1/92
  469. X
  470. X.SH EXAMPLE
  471. X.nf
  472. X#include    <var.H>
  473. X
  474. Xmain ()
  475. X{
  476. X    var value;                // declare an "untyped" var
  477. X    value = "hello world";        // initialize it
  478. X    cout << value << "\n";        // output "hello world"
  479. X    value = value(3, value.length() - 6); // substring example
  480. X    cout << value << "\n";        // output "lo wo"
  481. X    value = 34;                // assignment of int
  482. X    value++;                // increment
  483. X    value += 42.375;            // add 42.375 to present value
  484. X    cout << value << "\n";        // output "77.375"
  485. X    cout << value.format("formatted output example %05d of value\n");
  486. X    cout << value.format("multiple outputs #1=%d, #2=%9.2f of value\n");
  487. X    value.null(2);            // truncate string
  488. X    value += " sunset strip";        // concatenate a string
  489. X    cout << value.format("%s\n");    // output "77 sunset strip"
  490. X    cout << value[3] << value[4] << value[5] << "\n"; // output "sun"
  491. X}
  492. X.fi
  493. X
  494. X.SH SUPERCLASSES
  495. Xnone.
  496. X
  497. X.SH SUBCLASSES
  498. Xnone
  499. X
  500. X.SH BUGS
  501. XAssignment of an array of vars to another array of vars
  502. Xmust currently be done one element at a time.
  503. XVar now works with g++. (version 1.1)
  504. XString contatenation problem fixed. (version 1.1)
  505. XMemory leak fixed. (version 1.1)
  506. X
  507. END_OF_FILE
  508.   if test 15362 -ne `wc -c <'var.3++'`; then
  509.     echo shar: \"'var.3++'\" unpacked with wrong size!
  510.   fi
  511.   # end of 'var.3++'
  512. fi
  513. if test -f 'var.C' -a "${1}" != "-c" ; then 
  514.   echo shar: Will not clobber existing file \"'var.C'\"
  515. else
  516.   echo shar: Extracting \"'var.C'\" \(31997 characters\)
  517.   sed "s/^X//" >'var.C' <<'END_OF_FILE'
  518. X//
  519. X// NAME:    var.C
  520. X//
  521. X// PURPOSE:    C++ Generic "Universal Variable" library class
  522. X// VERSION:    1.1
  523. X// AUTHOR:    Lee Hounshell
  524. X// LAST MOD:    Mon Nov 23 08:56:24 PST 1992
  525. X//
  526. X
  527. X#include    <stddef.h>
  528. X#include    <stream.h>
  529. X#include    <stdlib.h>
  530. X#include    <ctype.h>
  531. X#include    <string.h>
  532. X#include    <memory.h>
  533. X#include    "var.H"
  534. X
  535. Xconst int    VAR_PAD_SIZE        = 128;
  536. Xconst int    VAR_DEF_SIZE        = 16;
  537. X
  538. Xconst short    VAR_STRING        = 0;
  539. Xconst short    VAR_LONG        = 1;
  540. Xconst short    VAR_DOUBLE        = 2;
  541. X
  542. Xchar *    DEFAULT_STRING_FORMAT        = "'%s'";
  543. Xchar *    DEFAULT_INT_FORMAT        = "%d";
  544. Xchar *    DEFAULT_UINT_FORMAT        = "%u";
  545. Xchar *    DEFAULT_LONG_FORMAT        = "%ld";
  546. Xchar *    DEFAULT_ULONG_FORMAT        = "%lu";
  547. Xchar *    DEFAULT_DOUBLE_FORMAT        = "%9.2f";
  548. X
  549. X// -----------------------------------------------------------------------------
  550. X
  551. X
  552. Xconst var & var::type(void) const
  553. X{
  554. X    static const var objtype = "var";
  555. X    return objtype;
  556. X}
  557. X
  558. X
  559. Xvarsize::varsize(int sz)
  560. X{
  561. X    size = sz;
  562. X}
  563. X
  564. X
  565. Xvar::var(void)
  566. X{
  567. X    fixed = 0;
  568. X    is_numeric = VAR_STRING;
  569. X    data_str_len = VAR_DEF_SIZE;
  570. X    data_str_end = 0;
  571. X    data_str = new char[data_str_len];
  572. X    data_str[0] = 0;
  573. X    format_str = DEFAULT_STRING_FORMAT;
  574. X}
  575. X
  576. X
  577. Xvar::var(const char *str)
  578. X{
  579. X    fixed = 1;
  580. X    is_numeric = VAR_STRING;
  581. X    data_str_end = strlen(str);
  582. X    data_str_len = data_str_end + VAR_DEF_SIZE;
  583. X    data_str = new char[data_str_len];
  584. X    strcpy(data_str, str);
  585. X    format_str = DEFAULT_STRING_FORMAT;
  586. X}
  587. X
  588. X
  589. Xvar::var(const varsize &vsz)
  590. X{
  591. X    fixed = 0;
  592. X    is_numeric = VAR_STRING;
  593. X    data_str_len = vsz.size + VAR_DEF_SIZE;
  594. X    data_str_end = 0;
  595. X    data_str = new char[data_str_len];
  596. X    data_str[0] = 0;
  597. X    format_str = DEFAULT_STRING_FORMAT;
  598. X}
  599. X
  600. X
  601. Xvar::var(const char ch)
  602. X{
  603. X    fixed = 0;
  604. X    is_numeric = VAR_STRING;
  605. X    data_str_len = VAR_DEF_SIZE;
  606. X    data_str_end = 1;
  607. X    data_str = new char[data_str_len];
  608. X    data_str[0] = ch;
  609. X    data_str[1] = 0;
  610. X    format_str = DEFAULT_STRING_FORMAT;
  611. X}
  612. X
  613. X
  614. Xvar::var(const short int_num)
  615. X{
  616. X    fixed = 1;
  617. X    is_numeric = VAR_LONG;
  618. X    data_str_len = VAR_DEF_SIZE;
  619. X    data_str = new char[data_str_len];
  620. X    strcpy(data_str, itoa((const int) int_num));
  621. X    data_str_end = strlen(data_str);
  622. X    format_str = DEFAULT_INT_FORMAT;
  623. X}
  624. X
  625. X
  626. Xvar::var(const unsigned short int_num)
  627. X{
  628. X    fixed = 1;
  629. X    is_numeric = VAR_LONG;
  630. X    data_str_len = VAR_DEF_SIZE;
  631. X    data_str = new char[data_str_len];
  632. X    strcpy(data_str, itoa((const int) int_num));
  633. X    data_str_end = strlen(data_str);
  634. X    format_str = DEFAULT_UINT_FORMAT;
  635. X}
  636. X
  637. X
  638. Xvar::var(const int int_num)
  639. X{
  640. X    fixed = 1;
  641. X    is_numeric = VAR_LONG;
  642. X    data_str_len = VAR_DEF_SIZE;
  643. X    data_str = new char[data_str_len];
  644. X    strcpy(data_str, itoa(int_num));
  645. X    data_str_end = strlen(data_str);
  646. X    format_str = DEFAULT_INT_FORMAT;
  647. X}
  648. X
  649. X
  650. Xvar::var(const unsigned int int_num)
  651. X{
  652. X    fixed = 1;
  653. X    is_numeric = VAR_LONG;
  654. X    data_str_len = VAR_DEF_SIZE;
  655. X    data_str = new char[data_str_len];
  656. X    strcpy(data_str, itoa((const int) int_num));
  657. X    data_str_end = strlen(data_str);
  658. X    format_str = DEFAULT_UINT_FORMAT;
  659. X}
  660. X
  661. X
  662. Xvar::var(const long long_num)
  663. X{
  664. X    fixed = 1;
  665. X    is_numeric = VAR_LONG;
  666. X    data_str_len = VAR_DEF_SIZE;
  667. X    data_str = new char[data_str_len];
  668. X    strcpy(data_str, ltoa(long_num));
  669. X    data_str_end = strlen(data_str);
  670. X    format_str = DEFAULT_LONG_FORMAT;
  671. X}
  672. X
  673. X
  674. Xvar::var(const unsigned long long_num)
  675. X{
  676. X    fixed = 1;
  677. X    is_numeric = VAR_LONG;
  678. X    data_str_len = VAR_DEF_SIZE;
  679. X    data_str = new char[data_str_len];
  680. X    strcpy(data_str, ltoa(long_num));
  681. X    data_str_end = strlen(data_str);
  682. X    format_str = DEFAULT_ULONG_FORMAT;
  683. X}
  684. X
  685. X
  686. Xvar::var(const double double_num)
  687. X{
  688. X    fixed = 1;
  689. X    is_numeric = VAR_DOUBLE;
  690. X    data_str_len = VAR_DEF_SIZE;
  691. X    data_str = new char[data_str_len];
  692. X    strcpy(data_str, dtoa(double_num));
  693. X    data_str_end = strlen(data_str);
  694. X    format_str = DEFAULT_DOUBLE_FORMAT;
  695. X}
  696. X
  697. X
  698. Xvar::var(const var &v)
  699. X{
  700. X    fixed = v.fixed;
  701. X    is_numeric = v.is_numeric;
  702. X    if (v.data_str && v.data_str_end) {
  703. X    data_str_len = v.data_str_end + VAR_DEF_SIZE;
  704. X    data_str_end = v.data_str_end;
  705. X    data_str = new char[data_str_len];
  706. X    strcpy(data_str, v.data_str);
  707. X    }
  708. X    else {
  709. X    data_str_len = VAR_DEF_SIZE;
  710. X    data_str_end = 0;
  711. X    data_str = new char[data_str_len];
  712. X    data_str[0] = 0;
  713. X    }
  714. X    format_str = DEFAULT_STRING_FORMAT;
  715. X}
  716. X
  717. X
  718. Xvar::~var(void)
  719. X{
  720. X    if (data_str) {
  721. X    delete data_str;
  722. X    }
  723. X    if (format_str
  724. X    && format_str != DEFAULT_STRING_FORMAT
  725. X    && format_str != DEFAULT_INT_FORMAT
  726. X    && format_str != DEFAULT_UINT_FORMAT
  727. X    && format_str != DEFAULT_LONG_FORMAT
  728. X    && format_str != DEFAULT_ULONG_FORMAT
  729. X    && format_str != DEFAULT_DOUBLE_FORMAT) {
  730. X        delete format_str;
  731. X    }
  732. X}
  733. X
  734. X// -----------------------------------------------------------------------------
  735. X
  736. Xvar & var::operator = (const char *str)
  737. X{
  738. X    //
  739. X    if (fixed && is_numeric) {
  740. X    if (is_numeric == VAR_DOUBLE) {
  741. X        double d = atod((char *) str);
  742. X        *this = d;
  743. X    }
  744. X    else {
  745. X        long l = atol(str);
  746. X        *this = l;
  747. X    }
  748. X    }
  749. X    else {
  750. X    int len = strlen(str) + 1;
  751. X    if (data_str_len < len) {
  752. X        delete data_str;
  753. X        data_str_len = len;
  754. X        data_str = new char[data_str_len];
  755. X    }
  756. X    data_str_end = len - 1;
  757. X    strcpy(data_str, str);
  758. X    if (!fixed) {
  759. X        int str_is_numeric = numcheck(data_str);
  760. X        is_numeric = str_is_numeric;
  761. X    }
  762. X    }
  763. X    return *this;
  764. X}
  765. X
  766. X
  767. Xvar & var::operator = (const var &l)
  768. X{
  769. X    //
  770. X    if (this != &l) {
  771. X    if (data_str_len <= l.data_str_end) {
  772. X        delete data_str;
  773. X        data_str_len = l.data_str_end + VAR_DEF_SIZE;
  774. X        data_str = new char[data_str_len];
  775. X    }
  776. X    data_str_end = l.data_str_end;
  777. X    strncpy(data_str, l.data_str, l.data_str_end);
  778. X    data_str[data_str_end] = 0;
  779. X    if (!fixed) {
  780. X        is_numeric = numcheck(data_str);
  781. X    }
  782. X    //
  783. X    // Note: the output "format" of a var variable is preserved
  784. X    //
  785. X    }
  786. X    return *this;
  787. X}
  788. X
  789. X
  790. Xchar & var::operator [] (const int index)
  791. X{
  792. X    static char error_ch;
  793. X    if (index < 0) {
  794. X    cerr << "ERROR: " << " - var[" << index << "] negative index used.\n";
  795. X    error_ch = 0;
  796. X    return error_ch;
  797. X    }
  798. X    if (data_str_len <= index) {
  799. X    // this is technically a program error, but I'll be nice and extend the string's length
  800. X    data_str_len = index + VAR_PAD_SIZE;
  801. X    data_str_end = index + 1;
  802. X    char *buf = new char[data_str_len];
  803. X    sprintf(buf, "%-*.*s", data_str_end, data_str_end, data_str);
  804. X    delete data_str;
  805. X    data_str = buf;
  806. X    data_str[index] = 0;
  807. X    // cerr << "WARNING: " << " - var index '" << index << "' beyond current string boundary.\n";
  808. X    }
  809. X    while (data_str_end < index) {
  810. X    data_str[data_str_end++] = ' ';        // pad to index with spaces if necessary
  811. X    }
  812. X    if (data_str_end == index) {
  813. X    data_str[data_str_end] = 0;        // the end of a string is ALWAYS 0
  814. X    if ((data_str_end + 1) < data_str_len) {
  815. X        data_str[++data_str_end] = 0;    // the new end of string is also 0
  816. X    }
  817. X    }
  818. X    return data_str[index];
  819. X}
  820. X
  821. X
  822. X// for substrings
  823. Xsubvar & var::operator () (const int offset) const
  824. X{
  825. X    return operator () (offset, -1);
  826. X}
  827. X
  828. X
  829. X// for substrings
  830. Xsubvar & var::operator () (int offset, int length) const
  831. X{
  832. X    static subvar _esi_subvar;
  833. X    if (length < 0) {
  834. X    length = data_str_end - offset;
  835. X    }
  836. X    char *substr = new char[length + 1];
  837. X    strncpy(substr, data_str + offset, (int) length);
  838. X    substr[length] = 0;
  839. X    _esi_subvar.var::operator = (substr);
  840. X    _esi_subvar.varptr = (var *) this;
  841. X    _esi_subvar.offset = offset;
  842. X    _esi_subvar.length = length;
  843. X    delete substr;
  844. X    return _esi_subvar;
  845. X}
  846. X
  847. X
  848. X// for syntax: var(offset, length) = var
  849. Xvar & subvar::operator = (const var &substr)
  850. X{
  851. X    char *srcstr = varptr->data_str;
  852. X    char *repstr = substr.data_str;
  853. X    int replen = length;
  854. X    if (substr.data_str_end < length) {
  855. X    replen = substr.data_str_end;
  856. X    }
  857. X    int len = varptr->data_str_len;
  858. X    char *newstr = new char[len];
  859. X    strncpy(newstr, srcstr, offset);        // data from string being replaced up to "offset"
  860. X    if (replen) {
  861. X    strncpy(newstr + offset, repstr, replen);    // replacement string data
  862. X    }
  863. X    int newoffset = offset + replen;
  864. X    if (newoffset < varptr->data_str_end) {
  865. X    strcpy(newstr + newoffset, srcstr + offset + length);
  866. X    }
  867. X    else {
  868. X    newstr[newoffset] = 0;
  869. X    }
  870. X    if (varptr->data_str) {
  871. X    delete varptr->data_str;
  872. X    }
  873. X    varptr->data_str = newstr;
  874. X    varptr->data_str_len = len;
  875. X    varptr->data_str_end = strlen(newstr);
  876. X    if (!varptr->fixed) {
  877. X    varptr->is_numeric = numcheck(newstr);
  878. X    }
  879. X    return *varptr;
  880. X}
  881. X
  882. X// -----------------------------------------------------------------------------
  883. X
  884. Xvar & var::operator = (const char ch)
  885. X{
  886. X    char buf[2];
  887. X    buf[0] = ch;
  888. X    buf[1] = 0;
  889. X    *this = buf;
  890. X    return *this;
  891. X}
  892. X
  893. X
  894. Xvar & var::operator = (const short int_num)
  895. X{
  896. X    char *str = itoa((const int) int_num);
  897. X    int len = strlen(str);
  898. X    if (data_str_len < len) {
  899. X    delete data_str;
  900. X    data_str_len = len + 1;
  901. X    data_str = new char[data_str_len];
  902. X    }
  903. X    data_str_end = len;
  904. X    strcpy(data_str, str);
  905. X    if (!fixed) {
  906. X    is_numeric = VAR_LONG;
  907. X    }
  908. X    return *this;
  909. X}
  910. X
  911. X
  912. Xvar & var::operator = (const unsigned short int_num)
  913. X{
  914. X    char *str = itoa((const int) int_num);
  915. X    int len = strlen(str);
  916. X    if (data_str_len < len) {
  917. X    delete data_str;
  918. X    data_str_len = len + 1;
  919. X    data_str = new char[data_str_len];
  920. X    }
  921. X    data_str_end = len;
  922. X    strcpy(data_str, str);
  923. X    is_numeric = VAR_LONG;
  924. X    return *this;
  925. X}
  926. X
  927. X
  928. Xvar & var::operator = (const int int_num)
  929. X{
  930. X    char *str = itoa(int_num);
  931. X    int len = strlen(str);
  932. X    if (data_str_len < len) {
  933. X    delete data_str;
  934. X    data_str_len = len + 1;
  935. X    data_str = new char[data_str_len];
  936. X    }
  937. X    data_str_end = len;
  938. X    strcpy(data_str, str);
  939. X    if (!fixed) {
  940. X    is_numeric = VAR_LONG;
  941. X    }
  942. X    return *this;
  943. X}
  944. X
  945. X
  946. Xvar & var::operator = (const unsigned int int_num)
  947. X{
  948. X    char *str = itoa((const int) int_num);
  949. X    int len = strlen(str);
  950. X    if (data_str_len < len) {
  951. X    delete data_str;
  952. X    data_str_len = len + 1;
  953. X    data_str = new char[data_str_len];
  954. X    }
  955. X    data_str_end = len;
  956. X    strcpy(data_str, str);
  957. X    if (!fixed) {
  958. X    is_numeric = VAR_LONG;
  959. X    }
  960. X    return *this;
  961. X}
  962. X
  963. X
  964. Xvar & var::operator = (const long long_num)
  965. X{
  966. X    char *str = ltoa(long_num);
  967. X    int len = strlen(str);
  968. X    if (data_str_len < len) {
  969. X    delete data_str;
  970. X    data_str_len = len + 1;
  971. X    data_str = new char[data_str_len];
  972. X    }
  973. X    data_str_end = len;
  974. X    strcpy(data_str, str);
  975. X    if (!fixed) {
  976. X    is_numeric = VAR_LONG;
  977. X    }
  978. X    return *this;
  979. X}
  980. X
  981. X
  982. Xvar & var::operator = (const unsigned long long_num)
  983. X{
  984. X    char *str = ltoa(long_num);
  985. X    int len = strlen(str);
  986. X    if (data_str_len < len) {
  987. X    delete data_str;
  988. X    data_str_len = len + 1;
  989. X    data_str = new char[data_str_len];
  990. X    }
  991. X    data_str_end = len;
  992. X    strcpy(data_str, str);
  993. X    if (!fixed) {
  994. X    is_numeric = VAR_LONG;
  995. X    }
  996. X    return *this;
  997. X}
  998. X
  999. X
  1000. Xvar & var::operator = (const double dbl_num)
  1001. X{
  1002. X    char *str = dtoa(dbl_num);
  1003. X    int len = strlen(str);
  1004. X    if (data_str_len < len) {
  1005. X    delete data_str;
  1006. X    data_str_len = len + 1;
  1007. X    data_str = new char[data_str_len];
  1008. X    }
  1009. X    data_str_end = len;
  1010. X    strcpy(data_str, str);
  1011. X    if (!fixed) {
  1012. X    is_numeric = VAR_DOUBLE;
  1013. X    }
  1014. X    return *this;
  1015. X}
  1016. X
  1017. X// -----------------------------------------------------------------------------
  1018. X
  1019. Xvar::operator char * (void) const
  1020. X{
  1021. X    return data_str;
  1022. X}
  1023. X
  1024. X
  1025. Xvar::operator double (void) const
  1026. X{
  1027. X    return atod(data_str);
  1028. X}
  1029. X
  1030. X// -----------------------------------------------------------------------------
  1031. X
  1032. Xvar & var::operator ++ (void)        // increment (pre-index only)
  1033. X{
  1034. X    *this -= (-1);            // because of bug in g++
  1035. X    return *this;
  1036. X}
  1037. X
  1038. X
  1039. Xvar & var::operator -- (void)        // decrement (pre-index only)
  1040. X{
  1041. X    *this -= 1;
  1042. X    return *this;
  1043. X}
  1044. X
  1045. X
  1046. Xvar var::operator ! (void) const    // not
  1047. X{
  1048. X    var not(1);
  1049. X    if ((int) *this) {
  1050. X    not = 0;
  1051. X    }
  1052. X    return not;
  1053. X}
  1054. X
  1055. X// -----------------------------------------------------------------------------
  1056. X
  1057. Xvar var::operator + (const var & v) const    // addition OR concatenation
  1058. X{
  1059. X    var add;
  1060. X    if (is_numeric && v.is_numeric) {
  1061. X    // do math in the highest precision specified
  1062. X    int n_type = (is_numeric > v.is_numeric) ? is_numeric : v.is_numeric;
  1063. X    switch (n_type) {
  1064. X        case VAR_LONG:
  1065. X        add = (long) *this + (long) v;
  1066. X        break;
  1067. X        default:
  1068. X        // should be VAR_DOUBLE
  1069. X        add = (double) *this + (double) v;
  1070. X        break;
  1071. X    }
  1072. X    }
  1073. X    else {
  1074. X    // concatenate strings
  1075. X    add = (*this);
  1076. X    add.concat(v);
  1077. X    add.is_numeric = VAR_STRING;
  1078. X    }
  1079. X    return add;
  1080. X}
  1081. X
  1082. X
  1083. Xvar var::operator - (const var & v) const    // subtraction
  1084. X{
  1085. X    var sub;
  1086. X    // do math in the highest precision specified
  1087. X    int n_type = (is_numeric > v.is_numeric) ? is_numeric : v.is_numeric;
  1088. X    switch (n_type) {
  1089. X    case VAR_LONG:
  1090. X        sub = (long) *this - (long) v;
  1091. X        sub.is_numeric = VAR_LONG;
  1092. X        break;
  1093. X    default:
  1094. X        // should be VAR_DOUBLE
  1095. X        sub = (double) *this - (double) v;
  1096. X        break;
  1097. X    }
  1098. X    return sub;
  1099. X}
  1100. X
  1101. X
  1102. Xvar var::operator * (const var & v) const    // multiplication
  1103. X{
  1104. X    var times;
  1105. X    // do math in the highest precision specified
  1106. X    int n_type = (is_numeric > v.is_numeric) ? is_numeric : v.is_numeric;
  1107. X    switch (n_type) {
  1108. X    case VAR_LONG:
  1109. X        times = (long) *this * (long) v;
  1110. X        break;
  1111. X    default:
  1112. X        // should be VAR_DOUBLE
  1113. X        times = (double) *this * (double) v;
  1114. X        break;
  1115. X    }
  1116. X    return times;
  1117. X}
  1118. X
  1119. X
  1120. Xvar var::operator / (const var & v) const    // division
  1121. X{
  1122. X    var div;
  1123. X    // do math in the highest precision specified
  1124. X    int n_type = (is_numeric > v.is_numeric) ? is_numeric : v.is_numeric;
  1125. X    switch (n_type) {
  1126. X    case VAR_LONG:
  1127. X        div = (long) *this / (long) v;
  1128. X        break;
  1129. X    default:
  1130. X        // should be VAR_DOUBLE
  1131. X        div = (double) *this / (double) v;
  1132. X        break;
  1133. X    }
  1134. X    return div;
  1135. X}
  1136. X
  1137. X
  1138. Xvar var::operator % (const var & v) const    // remainder
  1139. X{
  1140. X    var mod;
  1141. X    // do math in the highest precision specified
  1142. X    int n_type = (is_numeric > v.is_numeric) ? is_numeric : v.is_numeric;
  1143. X    switch (n_type) {
  1144. X    case VAR_LONG:
  1145. X        mod = (long) *this % (long) v;
  1146. X        break;
  1147. X    default:
  1148. X        // should be VAR_DOUBLE
  1149. X        // really, I shouldn't allow this..
  1150. X        mod = (double) ((long) *this % (long) v);
  1151. X        break;
  1152. X    }
  1153. X    return mod;
  1154. X}
  1155. X
  1156. X// -----------------------------------------------------------------------------
  1157. X
  1158. Xvar & var::operator += (const var & v)
  1159. X{
  1160. X    if ((is_numeric == VAR_STRING) || (v.is_numeric == VAR_STRING)) {
  1161. X    concat(v);
  1162. X    }
  1163. X    else {
  1164. X    *this = (*this) + v;
  1165. X    }
  1166. X    return *this;
  1167. X}
  1168. X
  1169. X
  1170. Xvar & var::operator -= (const var & v)
  1171. X{
  1172. X    *this = (*this) - v;
  1173. X    return *this;
  1174. X}
  1175. X
  1176. X
  1177. Xvar & var::operator *= (const var & v)
  1178. X{
  1179. X    *this = (*this) * v;
  1180. X    return *this;
  1181. X}
  1182. X
  1183. X
  1184. Xvar & var::operator /= (const var & v)
  1185. X{
  1186. X    *this = (*this) / v;
  1187. X    return *this;
  1188. X}
  1189. X
  1190. X
  1191. Xvar & var::operator %= (const var & v)
  1192. X{
  1193. X    *this = (*this) % v;
  1194. X    return *this;
  1195. X}
  1196. X
  1197. X// -----------------------------------------------------------------------------
  1198. X
  1199. Xvar & var::operator += (const char & ch)
  1200. X{
  1201. X    var foo = ch;
  1202. X    *this += foo;
  1203. X    return *this;
  1204. X}
  1205. X
  1206. Xvar & var::operator += (const char * v)
  1207. X{
  1208. X    var foo = v;
  1209. X    *this += foo;
  1210. X    return *this;
  1211. X}
  1212. X
  1213. X
  1214. Xvar & var::operator -= (const char * v)
  1215. X{
  1216. X    var foo = v;
  1217. X    *this -= foo;
  1218. X    return *this;
  1219. X}
  1220. X
  1221. X
  1222. Xvar & var::operator *= (const char * v)
  1223. X{
  1224. X    var foo = v;
  1225. X    *this *= foo;
  1226. X    return *this;
  1227. X}
  1228. X
  1229. X
  1230. Xvar & var::operator /= (const char * v)
  1231. X{
  1232. X    var foo = v;
  1233. X    *this /= foo;
  1234. X    return *this;
  1235. X}
  1236. X
  1237. X
  1238. Xvar & var::operator %= (const char * v)
  1239. X{
  1240. X    var foo = v;
  1241. X    *this %= foo;
  1242. X    return *this;
  1243. X}
  1244. X
  1245. X// -----------------------------------------------------------------------------
  1246. X
  1247. Xvar & var::operator += (const double v)
  1248. X{
  1249. X    var foo = v;
  1250. X    *this += foo;
  1251. X    return *this;
  1252. X}
  1253. X
  1254. X
  1255. Xvar & var::operator -= (const double v)
  1256. X{
  1257. X    var foo = v;
  1258. X    *this -= foo;
  1259. X    return *this;
  1260. X}
  1261. X
  1262. X
  1263. Xvar & var::operator *= (const double v)
  1264. X{
  1265. X    var foo = v;
  1266. X    *this *= foo;
  1267. X    return *this;
  1268. X}
  1269. X
  1270. X
  1271. Xvar & var::operator /= (const double v)
  1272. X{
  1273. X    var foo = v;
  1274. X    *this /= foo;
  1275. X    return *this;
  1276. X}
  1277. X
  1278. X
  1279. Xvar & var::operator %= (const double v)
  1280. X{
  1281. X    var foo = v;
  1282. X    *this %= foo;
  1283. X    return *this;
  1284. X}
  1285. X
  1286. X// -----------------------------------------------------------------------------
  1287. X
  1288. Xvar operator + (const char * s, const var & v)
  1289. X{
  1290. X    var foo = s;
  1291. X    return foo + v;
  1292. X}
  1293. X
  1294. X
  1295. Xvar operator - (const char * s, const var & v)
  1296. X{
  1297. X    var foo = s;
  1298. X    return foo - v;
  1299. X}
  1300. X
  1301. X
  1302. Xvar operator * (const char * s, const var & v)
  1303. X{
  1304. X    var foo = s;
  1305. X    return foo * v;
  1306. X}
  1307. X
  1308. X
  1309. Xvar operator / (const char * s, const var & v)
  1310. X{
  1311. X    var foo = s;
  1312. X    return foo / v;
  1313. X}
  1314. X
  1315. X
  1316. Xvar operator % (const char * s, const var & v)
  1317. X{
  1318. X    var foo = s;
  1319. X    return foo % v;
  1320. X}
  1321. X
  1322. X
  1323. Xvar operator + (const var & v, const char * s)
  1324. X{
  1325. X    var foo = s;
  1326. X    return v + foo;
  1327. X}
  1328. X
  1329. X
  1330. Xvar operator - (const var & v, const char * s)
  1331. X{
  1332. X    var foo = s;
  1333. X    return v - foo;
  1334. X}
  1335. X
  1336. X
  1337. Xvar operator * (const var & v, const char * s)
  1338. X{
  1339. X    var foo = s;
  1340. X    return v * foo;
  1341. X}
  1342. X
  1343. X
  1344. Xvar operator / (const var & v, const char * s)
  1345. X{
  1346. X    var foo = s;
  1347. X    return v / foo;
  1348. X}
  1349. X
  1350. X
  1351. Xvar operator % (const var & v, const char * s)
  1352. X{
  1353. X    var foo = s;
  1354. X    return v % foo;
  1355. X}
  1356. X
  1357. X// -----------------------------------------------------------------------------
  1358. X
  1359. Xvar operator + (const var & v, const double d)
  1360. X{
  1361. X    var foo = d;
  1362. X    return v + foo;
  1363. X}
  1364. X
  1365. X
  1366. Xvar operator - (const var & v, const double d)
  1367. X{
  1368. X    var foo = d;
  1369. X    return v - foo;
  1370. X}
  1371. X
  1372. X
  1373. Xvar operator * (const var & v, const double d)
  1374. X{
  1375. X    var foo = d;
  1376. X    return v * foo;
  1377. X}
  1378. X
  1379. X
  1380. Xvar operator / (const var & v, const double d)
  1381. X{
  1382. X    var foo = d;
  1383. X    return v / foo;
  1384. X}
  1385. X
  1386. X
  1387. Xvar operator % (const var & v, const double d)
  1388. X{
  1389. X    var foo = d;
  1390. X    return v % foo;
  1391. X}
  1392. X
  1393. X
  1394. Xvar operator + (const double d, const var & v)
  1395. X{
  1396. X    var foo = d;
  1397. X    return foo + v;
  1398. X}
  1399. X
  1400. X
  1401. Xvar operator - (const double d, const var & v)
  1402. X{
  1403. X    var foo = d;
  1404. X    return foo - v;
  1405. X}
  1406. X
  1407. X
  1408. Xvar operator * (const double d, const var & v)
  1409. X{
  1410. X    var foo = d;
  1411. X    return foo * v;
  1412. X}
  1413. X
  1414. X
  1415. Xvar operator / (const double d, const var & v)
  1416. X{
  1417. X    var foo = d;
  1418. X    return foo / v;
  1419. X}
  1420. X
  1421. X
  1422. Xvar operator % (const double d, const var & v)
  1423. X{
  1424. X    var foo = d;
  1425. X    return foo % v;
  1426. X}
  1427. X
  1428. X// -----------------------------------------------------------------------------
  1429. X
  1430. Xint var::operator == (const var & t) const        // equality
  1431. X{
  1432. X    if (is_numeric && t.is_numeric) {
  1433. X    if (is_numeric == VAR_LONG && t.is_numeric == VAR_LONG) {
  1434. X        return (long) (*this) == (long) t;
  1435. X    }
  1436. X    return (double) (*this) == (double) t;
  1437. X    }
  1438. X    else {
  1439. X    if (data_str_end && t.data_str_end) {
  1440. X        return !strcmp(data_str, t.data_str);
  1441. X    }
  1442. X    else {
  1443. X        return data_str_end == t.data_str_end;
  1444. X    }
  1445. X    }
  1446. X}
  1447. X
  1448. X
  1449. Xint var::operator != (const var & t) const        // inequality
  1450. X{
  1451. X    if (is_numeric && t.is_numeric) {
  1452. X    if (is_numeric == VAR_LONG && t.is_numeric == VAR_LONG) {
  1453. X        return (long) (*this) != (long) t;
  1454. X    }
  1455. X    return (double) (*this) != (double) t;
  1456. X    }
  1457. X    else {
  1458. X    if (data_str_end && t.data_str_end) {
  1459. X        return strcmp(data_str, t.data_str);
  1460. X    }
  1461. X    else {
  1462. X        return data_str_end != t.data_str_end;
  1463. X    }
  1464. X    }
  1465. X}
  1466. X
  1467. X
  1468. Xint var::operator < (const var & t) const        // less than
  1469. X{
  1470. X    if (is_numeric && t.is_numeric) {
  1471. X    if (is_numeric == VAR_LONG && t.is_numeric == VAR_LONG) {
  1472. X        return (long) (*this) < (long) t;
  1473. X    }
  1474. X    return (double) (*this) < (double) t;
  1475. X    }
  1476. X    else {
  1477. X    if (data_str_end && t.data_str_end) {
  1478. X        return (strcmp(data_str, t.data_str) < 0);
  1479. X    }
  1480. X    else {
  1481. X        return data_str_end < t.data_str_end;
  1482. X    }
  1483. X    }
  1484. X}
  1485. X
  1486. X
  1487. Xint var::operator > (const var & t) const        // greater than
  1488. X{
  1489. X    if (is_numeric && t.is_numeric) {
  1490. X    if (is_numeric == VAR_LONG && t.is_numeric == VAR_LONG) {
  1491. X        return (long) (*this) > (long) t;
  1492. X    }
  1493. X    return (double) (*this) > (double) t;
  1494. X    }
  1495. X    else {
  1496. X    if (data_str_end && t.data_str_end) {
  1497. X        return (strcmp(data_str, t.data_str) > 0);
  1498. X    }
  1499. X    else {
  1500. X        return data_str_end > t.data_str_end;
  1501. X    }
  1502. X    }
  1503. X}
  1504. X
  1505. X
  1506. Xint var::operator <= (const var & t) const        // less than or equal
  1507. X{
  1508. X    if (is_numeric && t.is_numeric) {
  1509. X    if (is_numeric == VAR_LONG && t.is_numeric == VAR_LONG) {
  1510. X        return (long) (*this) <= (long) t;
  1511. X    }
  1512. X    return (double) (*this) <= (double) t;
  1513. X    }
  1514. X    else {
  1515. X    if (data_str_end && t.data_str_end) {
  1516. X        return (strcmp(data_str, t.data_str) <= 0);
  1517. X    }
  1518. X    else {
  1519. X        return data_str_end <= t.data_str_end;
  1520. X    }
  1521. X    }
  1522. X}
  1523. X
  1524. X
  1525. Xint var::operator >= (const var & t) const        // greater than or equal
  1526. X{
  1527. X    if (is_numeric && t.is_numeric) {
  1528. X    if (is_numeric == VAR_LONG && t.is_numeric == VAR_LONG) {
  1529. X        return (long) (*this) >= (long) t;
  1530. X    }
  1531. X    return (double) (*this) >= (double) t;
  1532. X    }
  1533. X    else {
  1534. X    if (data_str_end && t.data_str_end) {
  1535. X        return (strcmp(data_str, t.data_str) >= 0);
  1536. X    }
  1537. X    else {
  1538. X        return data_str_end >= t.data_str_end;
  1539. X    }
  1540. X    }
  1541. X}
  1542. X
  1543. X// -----------------------------------------------------------------------------
  1544. X
  1545. Xint operator == (const var & t, const char * s)
  1546. X{
  1547. X    var foo = s;
  1548. X    return t == foo;
  1549. X}
  1550. X
  1551. X
  1552. Xint operator != (const var & t, const char * s)
  1553. X{
  1554. X    var foo = s;
  1555. X    return t != foo;
  1556. X}
  1557. X
  1558. X
  1559. Xint operator < (const var & t, const char * s)
  1560. X{
  1561. X    var foo = s;
  1562. X    return t < foo;
  1563. X}
  1564. X
  1565. X
  1566. Xint operator > (const var & t, const char * s)
  1567. X{
  1568. X    var foo = s;
  1569. X    return t > foo;
  1570. X}
  1571. X
  1572. X
  1573. Xint operator <= (const var & t, const char * s)
  1574. X{
  1575. X    var foo = s;
  1576. X    return t <= foo;
  1577. X}
  1578. X
  1579. X
  1580. Xint operator >= (const var & t, const char * s)
  1581. X{
  1582. X    var foo = s;
  1583. X    return t >= foo;
  1584. X}
  1585. X
  1586. X
  1587. Xint operator == (const char * s, const var & t)
  1588. X{
  1589. X    var foo = s;
  1590. X    return foo == t;
  1591. X}
  1592. X
  1593. X
  1594. Xint operator != (const char * s, const var & t)
  1595. X{
  1596. X    var foo = s;
  1597. X    return foo != t;
  1598. X}
  1599. X
  1600. X
  1601. Xint operator < (const char * s, const var & t)
  1602. X{
  1603. X    var foo = s;
  1604. X    return foo < t;
  1605. X}
  1606. X
  1607. X
  1608. Xint operator > (const char * s, const var & t)
  1609. X{
  1610. X    var foo = s;
  1611. X    return foo > t;
  1612. X}
  1613. X
  1614. X
  1615. Xint operator <= (const char * s, const var & t)
  1616. X{
  1617. X    var foo = s;
  1618. X    return foo <= t;
  1619. X}
  1620. X
  1621. X
  1622. Xint operator >= (const char * s, const var & t)
  1623. X{
  1624. X    var foo = s;
  1625. X    return foo >= t;
  1626. X}
  1627. X
  1628. X// -----------------------------------------------------------------------------
  1629. X
  1630. Xint operator == (const var & t, const double d)
  1631. X{
  1632. X    return (double) t == d;
  1633. X}
  1634. X
  1635. X
  1636. Xint operator != (const var & t, const double d)
  1637. X{
  1638. X    return (double) t != d;
  1639. X}
  1640. X
  1641. X
  1642. Xint operator < (const var & t, const double d)
  1643. X{
  1644. X    return (double) t < d;
  1645. X}
  1646. X
  1647. X
  1648. Xint operator > (const var & t, const double d)
  1649. X{
  1650. X    return (double) t > d;
  1651. X}
  1652. X
  1653. X
  1654. Xint operator <= (const var & t, const double d)
  1655. X{
  1656. X    return (double) t <= d;
  1657. X}
  1658. X
  1659. X
  1660. Xint operator >= (const var & t, const double d)
  1661. X{
  1662. X    return (double) t >= d;
  1663. X}
  1664. X
  1665. X
  1666. Xint operator == (const double d, const var & t)
  1667. X{
  1668. X    return d == (double) t;
  1669. X}
  1670. X
  1671. X
  1672. Xint operator != (const double d, const var & t)
  1673. X{
  1674. X    return d != (double) t;
  1675. X}
  1676. X
  1677. X
  1678. Xint operator < (const double d, const var & t)
  1679. X{
  1680. X    return d < (double) t;
  1681. X}
  1682. X
  1683. X
  1684. Xint operator > (const double d, const var & t)
  1685. X{
  1686. X    return d > (double) t;
  1687. X}
  1688. X
  1689. X
  1690. Xint operator <= (const double d, const var & t)
  1691. X{
  1692. X    return d <= (double) t;
  1693. X}
  1694. X
  1695. X
  1696. Xint operator >= (const double d, const var & t)
  1697. X{
  1698. X    return d >= (double) t;
  1699. X}
  1700. X
  1701. X// -----------------------------------------------------------------------------
  1702. X
  1703. Xvoid var::null(int index)
  1704. X{
  1705. X    if (index >= data_str_len) {
  1706. X    cerr << "WARNING: " << " - var::null(" << index << ") - the index out of range.\n";
  1707. X    (*this)[index] = 0;
  1708. X    data_str_end = index;
  1709. X    }
  1710. X    else {
  1711. X    data_str[index] = 0;
  1712. X    data_str_end = index;
  1713. X    }
  1714. X}
  1715. X
  1716. X
  1717. Xvoid var::changesize(int newsize)
  1718. X{
  1719. X    if (newsize > data_str_len) {
  1720. X    char *buf = new char[newsize];
  1721. X    if (data_str) {
  1722. X        strncpy(buf, data_str, data_str_end);
  1723. X        buf[data_str_end] = 0;
  1724. X        delete data_str;
  1725. X    }
  1726. X    else {
  1727. X        *buf = 0;
  1728. X        data_str_end = 0;
  1729. X    }
  1730. X    data_str_len = newsize;
  1731. X    data_str = buf;
  1732. X    }
  1733. X}
  1734. X
  1735. X
  1736. Xint var::length(void) const
  1737. X{
  1738. X    return data_str_end;
  1739. X}
  1740. X
  1741. X
  1742. Xconst char * var::vartype(void) const
  1743. X{
  1744. X    switch (is_numeric) {
  1745. X    case VAR_STRING:
  1746. X        return "VAR_STRING";
  1747. X    case VAR_LONG:
  1748. X        return "VAR_LONG";
  1749. X    case VAR_DOUBLE:
  1750. X        return "VAR_DOUBLE";
  1751. X    }
  1752. X    return "var type unknown";
  1753. X}
  1754. X
  1755. X
  1756. Xvoid var::change_type(const char *ntype)
  1757. X{
  1758. X    if (ntype == NULL) {
  1759. X    return;
  1760. X    }
  1761. X    int index = strlen(ntype);
  1762. X    if (!index) {
  1763. X    return;
  1764. X    }
  1765. X    char *new_type = new char[index + 1];
  1766. X    if (ntype[0] == '(' && ntype[index - 1] == ')') {
  1767. X    strcpy(new_type, &ntype[1]);
  1768. X    index = strlen(new_type) - 1;
  1769. X    if (index <= 0) {
  1770. X        delete new_type;
  1771. X        return;
  1772. X    }
  1773. X    new_type[index] = 0;            // drop parens
  1774. X    }
  1775. X    else {
  1776. X    strcpy(new_type, ntype);
  1777. X    }
  1778. X    if (new_type[index - 1] == ' ') {
  1779. X    new_type[index - 1] = 0;
  1780. X    }
  1781. X    fixed = 1;
  1782. X    if (!strcmp(new_type, "var")) {
  1783. X    is_numeric = numcheck((const char *) *this);
  1784. X    }
  1785. X    else if (!strcmp(new_type, "string")) {
  1786. X    is_numeric = VAR_STRING;
  1787. X    }
  1788. X    else if (!strcmp(new_type, "short")) {
  1789. X    is_numeric = VAR_LONG;
  1790. X    }
  1791. X    else if (!strcmp(new_type, "unsigned short")) {
  1792. X    is_numeric = VAR_LONG;
  1793. X    }
  1794. X    else if (!strcmp(new_type, "int")) {
  1795. X    is_numeric = VAR_LONG;
  1796. X    }
  1797. X    else if (!strcmp(new_type, "unsigned int")) {
  1798. X    is_numeric = VAR_LONG;
  1799. X    }
  1800. X    else if (!strcmp(new_type, "long")) {
  1801. X    is_numeric = VAR_LONG;
  1802. X    }
  1803. X    else if (!strcmp(new_type, "unsigned long")) {
  1804. X    is_numeric = VAR_LONG;
  1805. X    }
  1806. X    else if (!strcmp(new_type, "float")) {
  1807. X    is_numeric = VAR_DOUBLE;
  1808. X    }
  1809. X    else if (!strcmp(new_type, "double")) {
  1810. X    is_numeric = VAR_DOUBLE;
  1811. X    }
  1812. X    else {
  1813. X    cerr << "WARNING: " << " - change_type(" << new_type << ") - unrecognized type name.\n";
  1814. X    }
  1815. X    delete new_type;
  1816. X}
  1817. X
  1818. X
  1819. Xint var::is_string(void) const
  1820. X{
  1821. X    return is_numeric == VAR_STRING;
  1822. X}
  1823. X
  1824. X
  1825. Xint var::is_double(void) const
  1826. X{
  1827. X    return is_numeric == VAR_DOUBLE;
  1828. X}
  1829. X
  1830. X
  1831. Xint var::is_long(void) const
  1832. X{
  1833. X    return is_numeric == VAR_LONG;
  1834. X}
  1835. X
  1836. X
  1837. Xint var::strchr(const char ch) const
  1838. X{
  1839. X    for (int i = 0; i < data_str_end; ++i) {
  1840. X    if (data_str[i] == ch) {
  1841. X        return i;
  1842. X    }
  1843. X    }
  1844. X    return -1;
  1845. X}
  1846. X
  1847. X
  1848. Xint var::strrchr(const char ch) const
  1849. X{
  1850. X    for (int i = data_str_end - 1; i >= 0; --i) {
  1851. X    if (data_str[i] == ch) {
  1852. X        return i;
  1853. X    }
  1854. X    }
  1855. X    return -1;
  1856. X}
  1857. X
  1858. X
  1859. Xvar & var::concat(const var & str)
  1860. X{
  1861. X    // concatenate strings
  1862. X    char *this_str = (char *) (*this);
  1863. X    char *strs_str = (char *) (str);
  1864. X    int this_len = strlen(this_str);
  1865. X    int strs_len = strlen(strs_str);
  1866. X    int new_data_str_end = data_str_end + str.data_str_end;
  1867. X    // will it fit in this var's memory?
  1868. X    if (new_data_str_end >= (this_len + strs_len)) {
  1869. X    var add;
  1870. X    add.data_str_len = this_len + strs_len + VAR_PAD_SIZE;
  1871. X    add.data_str_end = this_len + strs_len;
  1872. X    delete add.data_str;
  1873. X    add.data_str = new char[add.data_str_len];
  1874. X    strcpy(add.data_str, this_str);
  1875. X    strcpy((add.data_str) + this_len, strs_str);
  1876. X    *this = add;
  1877. X    }
  1878. X    else {
  1879. X    strcpy(data_str + this_len, strs_str);
  1880. X    data_str_end = this_len + strs_len;
  1881. X    }
  1882. X    return *this;
  1883. X}
  1884. X
  1885. X
  1886. Xvar & var::format(const char * fmt)
  1887. X{
  1888. X    if (format_str
  1889. X    && format_str != DEFAULT_STRING_FORMAT
  1890. X    && format_str != DEFAULT_INT_FORMAT
  1891. X    && format_str != DEFAULT_UINT_FORMAT
  1892. X    && format_str != DEFAULT_LONG_FORMAT
  1893. X    && format_str != DEFAULT_ULONG_FORMAT
  1894. X    && format_str != DEFAULT_DOUBLE_FORMAT) {
  1895. X        delete format_str;
  1896. X    }
  1897. X    if (fmt) {
  1898. X    format_str = new char[strlen(fmt) + 1];
  1899. X    strcpy(format_str, fmt);
  1900. X    }
  1901. X    else {
  1902. X    format_str = NULL;
  1903. X    }
  1904. X    return *this;
  1905. X}
  1906. X
  1907. X
  1908. Xint var::numcheck(const char * str) const
  1909. X{
  1910. X    if (!str || !*str) {
  1911. X    return VAR_STRING;        // assume a string
  1912. X    }
  1913. X    char *ptr = (char *) str;
  1914. X    int nc = VAR_LONG;            // assume a signed long
  1915. X    int decimal_yet = 0;
  1916. X    if (*ptr == '.' && *(ptr + 1)) {
  1917. X    nc = VAR_DOUBLE;        // floating point number
  1918. X    decimal_yet = 1;
  1919. X    ++ptr;
  1920. X    }
  1921. X    else if (*ptr == '-' && *(ptr + 1)) {
  1922. X    // skip optional sign char
  1923. X    ++ptr;
  1924. X    }
  1925. X    while (*ptr) {
  1926. X    if (*ptr == '.' && !decimal_yet) {
  1927. X        decimal_yet = 1;
  1928. X        nc = VAR_DOUBLE;        // assume a double
  1929. X    }
  1930. X    else if (!isdigit(*ptr)) {
  1931. X        return VAR_STRING;        // nope.. got a string
  1932. X    }
  1933. X    ++ptr;
  1934. X    }
  1935. X    return nc;
  1936. X}
  1937. X
  1938. X// -----------------------------------------------------------------------------
  1939. X
  1940. Xostream & operator << (ostream &out, const var &d)
  1941. X{
  1942. X    d.print(out);
  1943. X    return out;
  1944. X}
  1945. X
  1946. X
  1947. Xvoid var::print(ostream &out) const
  1948. X{
  1949. X    // NOTE: the "read()" function requires a newline to appear after the last quote.
  1950. X    // I assume that this newline was appropriately output by the var class user.
  1951. X    if (!format_str || (format_str && *format_str == 0)) {
  1952. X    out << "var OBJECT: {"
  1953. X        << "\n\tfixed        = " << fixed
  1954. X        << "\n\tis_numeric   = " << is_numeric
  1955. X        << "\n\tdata_str_len = " << data_str_len
  1956. X        << "\n\tdata_str_end = " << data_str_end
  1957. X        << "\n\tdata_str     = '" << data_str << "'"
  1958. X        << "\n\tformat_str   = '" << format_str << "'"
  1959. X        << "\n}\n";
  1960. X    }
  1961. X    else {
  1962. X    // we need to use the specified format string for output
  1963. X    int len = length() + 1;
  1964. X    char *outbuf = new char[2048];
  1965. X    char *fptr = format_str;
  1966. X    while (*fptr) {
  1967. X        if (*fptr != '%' && *fptr != '\\') {
  1968. X        out << *fptr;
  1969. X        ++fptr;
  1970. X        }
  1971. X        else if (*fptr == '\\') {
  1972. X        switch (*(fptr + 1)) {
  1973. X            case 'n':
  1974. X            cout << '\n';
  1975. X            break;
  1976. X            case 't':
  1977. X            cout << '\t';
  1978. X            break;
  1979. X            case 'v':
  1980. X            cout << '\v';
  1981. X            break;
  1982. X            case 'b':
  1983. X            cout << '\b';
  1984. X            break;
  1985. X            case 'r':
  1986. X            cout << '\r';
  1987. X            break;
  1988. X            case 'f':
  1989. X            cout << '\f';
  1990. X            break;
  1991. X            case 'a':
  1992. X            cout << '\007';
  1993. X            break;
  1994. X            case '\\':
  1995. X            cout << '\\';
  1996. X            break;
  1997. X            case '?':
  1998. X            cout << '\?';
  1999. X            break;
  2000. X            case '\'':
  2001. X            cout << '\'';
  2002. X            break;
  2003. X            case '\"':
  2004. X            cout << '\"';
  2005. X            break;
  2006. X            default:
  2007. X            cout << *(fptr + 1);
  2008. X        }
  2009. X        fptr += 2;
  2010. X        }
  2011. X        else {
  2012. X        // Hmmm.. we need to do some special formatting
  2013. X        // first extract this printf-style format string
  2014. X        char smallfmtstr[128];
  2015. X        char *smptr = smallfmtstr;
  2016. X        *smptr = 0;
  2017. X        if (*(fptr + 1) == '%') {
  2018. X            strcpy(outbuf, "%");
  2019. X            fptr += 2;
  2020. X        }
  2021. X        else {
  2022. X            while (*fptr) {
  2023. X            *smptr = *fptr++;
  2024. X            *(smptr + 1) = 0;
  2025. X            // integer
  2026. X            if (*smptr == 'd') {
  2027. X                sprintf(outbuf, smallfmtstr, (int) *this);
  2028. X                break;
  2029. X            }
  2030. X            // unsigned integer
  2031. X            if (*smptr == 'o' || *smptr == 'u' || *smptr == 'x' || *smptr == 'X') {
  2032. X                sprintf(outbuf, smallfmtstr, (unsigned int) *this);
  2033. X                break;
  2034. X            }
  2035. X            // float or double
  2036. X            if (*smptr == 'f' || *smptr == 'e' || *smptr == 'E' || *smptr == 'g' || *smptr == 'G') {
  2037. X                sprintf(outbuf, smallfmtstr, (double) *this);
  2038. X                break;
  2039. X            }
  2040. X            // character
  2041. X            if (*smptr == 'c') {
  2042. X                if (!strcmp(vartype(), "VAR_STRING")) {
  2043. X                const char *tmp = (const char *) (*this);
  2044. X                sprintf(outbuf, smallfmtstr, tmp[0]);
  2045. X                }
  2046. X                else {
  2047. X                sprintf(outbuf, smallfmtstr, (char) ((int) *this));
  2048. X                }
  2049. X                break;
  2050. X            }
  2051. X            // string
  2052. X            if (*smptr == 's') {
  2053. X                sprintf(outbuf, smallfmtstr, (const char *) *this);
  2054. X                break;
  2055. X            }
  2056. X            ++smptr;
  2057. X            }
  2058. X        }
  2059. X        out << outbuf;
  2060. X        }
  2061. X    }
  2062. X    //out << flush;
  2063. X    delete outbuf;
  2064. X    }
  2065. X}
  2066. X
  2067. X// -----------------------------------------------------------------------------
  2068. X
  2069. X// convert an integer into an ascii string.  return a pointer to that string.
  2070. X//
  2071. Xchar *itoa(const int foo)
  2072. X{
  2073. X    static char int_buf[28];
  2074. X    sprintf(int_buf, "%d", foo);
  2075. X    return int_buf;
  2076. X}
  2077. X
  2078. X
  2079. X// convert an unsigned integer into an ascii string.  return a pointer to that string.
  2080. X//
  2081. Xchar *uitoa(const unsigned int foo)
  2082. X{
  2083. X    static char int_buf[28];
  2084. X    sprintf(int_buf, "%u", foo);
  2085. X    return int_buf;
  2086. X}
  2087. X
  2088. X
  2089. X// convert a long into an ascii string.  return a pointer to that string.
  2090. X//
  2091. X#ifdef HP
  2092. Xchar *ltoa(long foo)
  2093. X#else
  2094. Xchar *ltoa(const long foo)
  2095. X#endif
  2096. X{
  2097. X    static char long_buf[28];
  2098. X    sprintf(long_buf, "%ld", foo);
  2099. X    return long_buf;
  2100. X}
  2101. X
  2102. X
  2103. X// convert an unsigned long into an ascii string.  return a pointer to that string.
  2104. X//
  2105. X#ifdef HP
  2106. Xchar *ultoa(unsigned long foo)
  2107. X#else
  2108. Xchar *ultoa(const unsigned long foo)
  2109. X#endif
  2110. X{
  2111. X    static char long_buf[28];
  2112. X    sprintf(long_buf, "%lu", foo);
  2113. X    return long_buf;
  2114. X}
  2115. X
  2116. X
  2117. X// convert a double into an ascii string.  return a pointer to that string.
  2118. X// truncate any extra zeros after the decimal point.
  2119. X//
  2120. Xchar *dtoa(const double foo)
  2121. X{
  2122. X    static char double_buf[28];
  2123. X    sprintf(double_buf, "%lf", foo);
  2124. X    char *ptr;
  2125. X    for (ptr = double_buf; *ptr; ++ptr) {
  2126. X    if (*ptr == '.') {
  2127. X        // we may need to truncate zeroes
  2128. X        ptr = double_buf + (strlen(double_buf) - 1);
  2129. X        while (*ptr == '0') {
  2130. X        *ptr-- = 0;
  2131. X        }
  2132. X        if (*ptr == '.') {
  2133. X        *ptr = 0;
  2134. X        }
  2135. X        break;
  2136. X    }
  2137. X    }
  2138. X    return double_buf;
  2139. X}
  2140. X
  2141. X
  2142. X// convert an ascii string to a double
  2143. X//
  2144. Xdouble atod(char * foo)
  2145. X{
  2146. X    double d = 0;
  2147. X    if (!foo || !*foo) {
  2148. X    return d;
  2149. X    }
  2150. X    if (!isdigit(*foo)) {
  2151. X    if (*foo != '-' && *foo != '+') {
  2152. X        return d;
  2153. X    }
  2154. X    if (!isdigit(*(foo + 1))) {
  2155. X        return d;
  2156. X    }
  2157. X    }
  2158. X    sscanf(foo, "%lf", &d);
  2159. X    return d;
  2160. X}
  2161. X
  2162. END_OF_FILE
  2163.   if test 31997 -ne `wc -c <'var.C'`; then
  2164.     echo shar: \"'var.C'\" unpacked with wrong size!
  2165.   fi
  2166.   # end of 'var.C'
  2167. fi
  2168. echo shar: End of archive 1 \(of 2\).
  2169. cp /dev/null ark1isdone
  2170. MISSING=""
  2171. for I in 1 2 ; do
  2172.     if test ! -f ark${I}isdone ; then
  2173.     MISSING="${MISSING} ${I}"
  2174.     fi
  2175. done
  2176. if test "${MISSING}" = "" ; then
  2177.     echo You have unpacked both archives.
  2178.     rm -f ark[1-9]isdone
  2179. else
  2180.     echo You still must unpack the following archives:
  2181.     echo "        " ${MISSING}
  2182. fi
  2183. exit 0
  2184. exit 0 # Just in case...
  2185.