home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #30 / NN_1992_30.iso / spool / comp / sources / misc / 4164 < prev    next >
Encoding:
Text File  |  1992-12-12  |  38.8 KB  |  1,575 lines

  1. Newsgroups: comp.sources.misc
  2. Path: sparky!kent
  3. From: kirkwood@qucis.queensu.ca (Scott Kirkwood)
  4. Subject:  v34i024:  iformat - Fast C++ class for formatting integer numbers, Part01/01
  5. Message-ID: <1992Dec13.013941.26401@sparky.imd.sterling.com>
  6. Followup-To: comp.sources.d
  7. X-Md4-Signature: 9794428bdd46d24394911f6be6d1cd50
  8. Keywords: C++, integers, class
  9. Sender: kent@sparky.imd.sterling.com (Kent Landfield)
  10. Organization: Computing & Information Science, Queen's University at Kingston
  11. Date: Sun, 13 Dec 1992 01:39:41 GMT
  12. Approved: kent@sparky.imd.sterling.com
  13. Lines: 1560
  14.  
  15. Submitted-by: kirkwood@qucis.queensu.ca (Scott Kirkwood)
  16. Posting-number: Volume 34, Issue 24
  17. Archive-name: iformat/part01
  18. Environment: C++
  19.  
  20. WHAT IS IFormat?
  21. ================
  22.  
  23. IFormat is a C++ class that is designed to output formatted
  24. integers (int, long).  By formatted we mean:
  25.     1,234,567
  26.  
  27. One of the main concerns of IFormat was to make it FAST.
  28. On some Unix machines using gcc and CC IFormat was between
  29. 50% to 200% faster than sprintf() -- and sprintf won't put in commas!
  30. With Borland's C++ v3 IFormat was 25% to 50% SLOWER, darn.
  31. But with gcc 2.2.2 on the PC I got IFormat to be about even 
  32. in speed with sprintf().
  33.  
  34. Note that this is just a class to be plugged into your programs.  It
  35. is not a standalone program.
  36.  
  37. OTHER FEATURES
  38. ==============
  39.  
  40. IFormat can format to a specified total character width and if the
  41. number doesn't fit it will be divided down until it does and then
  42. the appropriate SI notation will be affixed.  For instance, if
  43. you gave IFormat the number 1234567 and set the width to 6 you would
  44. get:
  45.     1,234K
  46.  
  47. By default the postfixes are K=1,000,  M=1,000,000,  G=1,000,000,000
  48. but you can change these values if you prefer the computer science
  49. K = 1,024, for instance.
  50.  
  51. You can also have output in hexadecimal or octal.
  52.  
  53. IFormat will, by default, right adjust number if the ouput is smaller
  54. than the width passed.  Where a width of 0 signifies variable width.
  55. For instance, here's 123 with a width of 5 (vertical bars for clarity)
  56.     |  123|
  57.  
  58. You can toggle whether to use SI postfixes, right adjusting, and
  59. whether separators are used.
  60.  
  61. You can change the `separator width' to any number greater than 2.
  62. A common setting, for instance, is a separator width of 4 
  63. and the separator character set to a space.
  64.  
  65.     12 3456 7890
  66.  
  67. TESTED SYSTEMS
  68. ==============
  69.  
  70. IBM (Borland C++ 3.0, djgcc 2.2.2) and Unix (AT&T CC, GNU g++ 2.2.2).
  71.  
  72. COPYRIGHT
  73. =========
  74.  
  75. This is free software.  Use it and distribute it freely. Please keep
  76. the copyright notices.
  77.  
  78. -- CUT HERE -- CUT HERE -- CUT HERE -- CUT HERE -- CUT HERE -- CUT HERE --
  79. #! /bin/sh
  80. # This is a shell archive.  Remove anything before this line, then unpack
  81. # it by saving it into a file and typing "sh file".  To overwrite existing
  82. # files, type "sh file -c".  You can also feed this as standard input via
  83. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  84. # will see the following message at the end:
  85. #        "End of archive 1 (of 1)."
  86. # Contents:  MANIFEST Makefile README iformat.C iformat.h make.bor
  87. #   my.out test.C test.bat test.sh
  88. # Wrapped by kirkwood@gauss on Thu Dec 10 13:24:15 1992
  89. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  90. if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  91.   echo shar: Will not clobber existing file \"'MANIFEST'\"
  92. else
  93. echo shar: Extracting \"'MANIFEST'\" \(325 characters\)
  94. sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
  95. XMANIFEST 
  96. XREADME      More information
  97. Xiformat.C   Main C++ routines
  98. Xiformat.h   C++ header file (imbedded help)
  99. XMakefile    UNIX and GCC makefile
  100. Xmake.bor    Borland C++ makefile.
  101. Xtest.C      Test program
  102. Xtest.sh     Test file (Bourne Shell)
  103. Xtest.bat    Test file (DOS batch)
  104. Xmy.out        What my output was (for comparison)
  105. X
  106. END_OF_FILE
  107. if test 325 -ne `wc -c <'MANIFEST'`; then
  108.     echo shar: \"'MANIFEST'\" unpacked with wrong size!
  109. fi
  110. # end of 'MANIFEST'
  111. fi
  112. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  113.   echo shar: Will not clobber existing file \"'Makefile'\"
  114. else
  115. echo shar: Extracting \"'Makefile'\" \(749 characters\)
  116. sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  117. X.KEEP_STATE:
  118. X.SUFFIXES: .C .o  
  119. X
  120. X# Run "make test" to make test program (called iformat)
  121. X# Change to your C++ extensions on your system.
  122. X# (sometimes .c, .cxx, .cc, .cpp, .hpp, .obj)
  123. XC=.C
  124. XH=.h
  125. XO=.o
  126. X
  127. X# Name of your C++ compiler
  128. XCC=g++
  129. X#CC= CC
  130. X#CC=gcc
  131. X
  132. XPNAME =iformat 
  133. XFILES.C=$(PNAME)$(C) 
  134. XFILES.H=$(FILES.C:%$(C)=%$(H))
  135. XFILES.O=$(FILES.C:%$(C)=%$(O))
  136. X
  137. X# Use -O for optimizing and -g for debugging
  138. XCFLAGS=-O
  139. X#CFLAGS=-g
  140. X
  141. X# Set BIG_NUMBERS if your machine has 64 bit longs
  142. X#DEFS=-DBIG_NUMBERS
  143. X
  144. X$(C)$(O):
  145. X    $(CC) -I$(ARGS_D) $(CFLAGS) $(DEFS) -c $*$(C)
  146. X
  147. Xtest: iformat$(C) iformat$(H) test$(C)
  148. X    $(CC) $(DEFS) $(CFLAGS) test$(C) iformat$(C) -o iformat
  149. X
  150. Xclean:
  151. X    rm -f core *$(O) your.out $(PNAME) TAGS
  152. X
  153. X# Dependancy list
  154. X$(PNAME)$(O): $(FILES.C) $(FILES.H)
  155. END_OF_FILE
  156. if test 749 -ne `wc -c <'Makefile'`; then
  157.     echo shar: \"'Makefile'\" unpacked with wrong size!
  158. fi
  159. # end of 'Makefile'
  160. fi
  161. if test -f 'README' -a "${1}" != "-c" ; then 
  162.   echo shar: Will not clobber existing file \"'README'\"
  163. else
  164. echo shar: Extracting \"'README'\" \(5524 characters\)
  165. sed "s/^X//" >'README' <<'END_OF_FILE'
  166. XIFormat C++ class.
  167. X
  168. XWHAT IS IFormat?
  169. X================
  170. X
  171. XIFormat is a C++ class that is designed to output formatted
  172. Xintegers (int, long).  By formatted we mean:
  173. X    1,234,567
  174. X
  175. XOne of the main concerns of IFormat was to make it FAST.
  176. XOn some Unix machines using gcc and CC IFormat was between
  177. X50% to 200% faster than sprintf() -- and sprintf won't put in commas!
  178. XWith Borland's C++ v3 IFormat was 25% to 50% SLOWER, darn.
  179. XBut with gcc 2.2.2 on the PC I got IFormat to be about even 
  180. Xin speed with sprintf().
  181. X
  182. XNote that this is just a class to be plugged into your programs.  It
  183. Xis not a standalone program.
  184. X
  185. XOTHER FEATURES
  186. X==============
  187. X
  188. XIFormat can format to a specified total character width and if the
  189. Xnumber doesn't fit it will be divided down until it does and then
  190. Xthe appropriate SI notation will be affixed.  For instance, if
  191. Xyou gave IFormat the number 1234567 and set the width to 6 you would
  192. Xget:
  193. X    1,234K
  194. X
  195. XBy default the postfixes are K=1,000,  M=1,000,000,  G=1,000,000,000
  196. Xbut you can change these values if you prefer the computer science
  197. XK = 1,024, for instance.
  198. X
  199. XYou can also have output in hexadecimal or octal.
  200. X
  201. XIFormat will, by default, right adjust number if the ouput is smaller
  202. Xthan the width passed.  Where a width of 0 signifies variable width.
  203. XFor instance, here's 123 with a width of 5 (vertical bars for clarity)
  204. X    |  123|
  205. X
  206. XYou can toggle whether to use SI postfixes, right adjusting, and
  207. Xwhether separators are used.
  208. X
  209. XYou can change the `separator width' to any number greater than 2.
  210. XA common setting, for instance, is a separator width of 4 
  211. Xand the separator character set to a space.
  212. X
  213. X    12 3456 7890
  214. X
  215. XTESTING
  216. X=======
  217. X
  218. XUNIX
  219. X====
  220. X  Edit the Makefile for either CC or g++ (g++ by default).
  221. X  Run the Borne shell "test.sh" which will compile and run the
  222. X  demo program.  The shell also runs "diff" to see if your output
  223. X  is identical with my output.
  224. X
  225. XDOS
  226. X===
  227. X  Rename all the .c files to .cc (or .cpp or whatever your standard is).
  228. X
  229. X  Borland
  230. X  -------
  231. X  Either edit the file "make.bor" or open a new project and add the
  232. X  two (renamed) files to the project list.  Press F9 to make (as usual).
  233. X   -or-
  234. X  If you edited the file "make.bor" then run "make -f make.bor".
  235. X
  236. X  GCC
  237. X  ---
  238. X  Edit the file Makefile.  Uncomment the "CC=gcc".  Change C to "C=.cc"
  239. X  Edit the file "test.bat" so that it will run go32.
  240. X
  241. X  Both
  242. X  ----
  243. X  Run "test.bat"
  244. X
  245. XIf you have longs that are 64 bits long then you will need to compile
  246. Xwith -DBIG_NUMBERS switch set.  (Although I haven't tested to see if
  247. Xthis really works -- e-mail me if it does!).
  248. X
  249. XI've included every test I could think of (with the help of a profiler).
  250. X
  251. XEXAMPLE
  252. X=======
  253. X
  254. X#include <iostream.h>
  255. X#include "iformat.h"
  256. X
  257. Xmain() {
  258. X    IFormat a;
  259. X
  260. X    a.SetWidth(5);
  261. X    cout << '|' << a.Str(12345) << '|' << endl;
  262. X    a.SetWidth(6);
  263. X    cout << '|' << a.Str(12345) << '|' << endl;
  264. X    a.SetWidth(7);
  265. X    cout << '|' << a.Str(12345) << '|' << endl;
  266. X}
  267. X
  268. Xproduces:
  269. X    |  12K|
  270. X    |12,345|
  271. X    | 12,345|
  272. X
  273. X
  274. XCLASS DEFINITION
  275. X================
  276. X
  277. Xclass IFormat{
  278. X//  Private stuff
  279. Xpublic:
  280. X    IFormat(); // Constructor
  281. X
  282. X    const char *Str(signed int num);    // Use Str, it's overloaded
  283. X    const char *Str(signed long num);
  284. X    const char *Str(unsigned int num);
  285. X    const char *Str(unsigned long num); // main routine
  286. X    const char *Str(char num); // why not?
  287. X
  288. X    // Mutators
  289. X    void  SetSepWidth(int i);  // Default is 3 but 4 is nice too
  290. X    void  SetWidth(int i);     // Default is 0 (for infinite)
  291. X    void  SetSep(char ch);     // Default is a comma (but space is nice too)
  292. X    void  SetUseSeparators(int i); // Default is to use separators
  293. X    void  SetRightAdjust(int i);   // Default is to right adjust numbers
  294. X    void  SetUseSI(int i);         // Default is to use SI postfix chars
  295. X    void  SetMode(int i);      // either ios::dec, ios::hex, ios::oct
  296. X    void  SetSI(int i, char c); // Set SI character (affects a static) 
  297. X    void  SetSI(int i, unsigned long div); // Set SI divisor (affects a static)
  298. X
  299. X    // Accessers
  300. X    int   SepWidth();  // returns width between separator characters
  301. X    int   Width();     // returns the format width set, not string width
  302. X    char  Sep();       // returns the separator character (usually comma)
  303. X    int   UseSeparators();
  304. X    int   RightAdjust(); // Used only if Width() != 0.
  305. X    int   UseSI();       // only applicable if Width() != 0.
  306. X};
  307. X
  308. XCAVEATS
  309. X=======
  310. X
  311. XIFormat returns a pointer to a string withing IFormat.  When the
  312. XIFormat instance is destroyed so is the string.  So in some cases you
  313. Xwill have to copy the string somewhere safe.  
  314. X
  315. XIf the string does not fit in width specified and every attempt has
  316. Xbeen made to shrink the string, then the string will be larger than
  317. Xthe width (instead of the other standard of putting ******).
  318. X
  319. XIFormat rounds down (aka floor).  For example, if you set a width of 2
  320. Xand passed the number 5678 would be converted to "5K" not "6K".
  321. X
  322. XYou cannot give a separation width less than 3.
  323. X
  324. XWidths that are too large for the class's internal string structure
  325. Xthe width will be set to the maximum allowable.
  326. X
  327. XAny changes you make to the SI characters ('K', 'M', etc.) and their
  328. Xvalues (1000, 1000000, etc.) will affect every instance of the class
  329. XIFormat (they're static).  
  330. X
  331. XTESTED SYSTEMS
  332. X==============
  333. X
  334. XIBM (Borland C++ 3.0, djgcc 2.2.2) and Unix (AT&T CC, GNU g++ 2.2.2).
  335. X
  336. XCOPYRIGHT
  337. X=========
  338. X
  339. XThis is free software.  Use it and distribute it freely. Please keep
  340. Xthe copyright notices.
  341. X
  342. XAUTHOR / ADDRESS
  343. X================
  344. X
  345. XScott Kirkwood : kirkwood@qucis.queensu.ca
  346. XVoice phone: (613) 531-2674
  347. XGraduate Studies - Computer Information Science
  348. XQueens University
  349. XKingston, CANADA
  350. END_OF_FILE
  351. if test 5524 -ne `wc -c <'README'`; then
  352.     echo shar: \"'README'\" unpacked with wrong size!
  353. fi
  354. # end of 'README'
  355. fi
  356. if test -f 'iformat.C' -a "${1}" != "-c" ; then 
  357.   echo shar: Will not clobber existing file \"'iformat.C'\"
  358. else
  359. echo shar: Extracting \"'iformat.C'\" \(9885 characters\)
  360. sed "s/^X//" >'iformat.C' <<'END_OF_FILE'
  361. X// Copyright (C) 1992 Scott Kirkwood (Queen's University, Ontario, Canada)
  362. X// Voice phone : (613) 531-2674, internet: kirkwood@qucis.queensu.ca
  363. X// This program is given as freeware with no warantees.  Not liable for
  364. X// any loss or damage resulting from this code.  Please acknowledge authorship.
  365. X// Note: Tabs in are size 4
  366. X
  367. X// IFormat.C : routines for the IFormat class.
  368. X// Please read IFormat.h for more information.
  369. X
  370. X#include "iformat.h"
  371. X#include <iostream.h>
  372. X#include <string.h>
  373. X#include <math.h>
  374. X
  375. X// Note: may get wrong results for negative number equal to LONGMIN
  376. X// I also haven't been able to test REALLY_BIG
  377. X// Notes to myself...
  378. X// 18,446,744,073,709,551,616  (64 bits) 20+6(commas)+3 = 29
  379. X//              2,147,483,647  (32 bits) 10+3+3(-,K,\0) = 16
  380. X
  381. X#ifndef REALLY_BIG
  382. X    char IFormat::ext[IFormatMAXSI] = {0, 'K', 'M', 'G'};
  383. X    unsigned long IFormat::divby[IFormatMAXSI] = {1, 1000, 1000000,
  384. X                                          1000000000};
  385. X#else
  386. X    const MAXSI = 5;
  387. X    char IFormat::ext[IFormatMAXSI] = {0, 'K', 'M', 'G','T'};
  388. X    unsigned long IFormat::divby[IFormatMAXSI] = {1, 1000, 1000000,
  389. X              1000000000, 1000000000000};
  390. X#endif
  391. X
  392. X// Function prototypes.
  393. Xchar* uconv10(unsigned long i, char* bufend, int &len);
  394. Xchar* conv8(register unsigned long i, register char* p, register int &len);
  395. Xchar* conv16(register unsigned long i, register char* p, register int &len);
  396. X
  397. X// ============================================================
  398. X// Author      : Scott Kirkwood
  399. X// Date        : Mon Nov  2 1992
  400. X//
  401. X// Prototype   : iformat.h
  402. X// Description :
  403. X// Constructor, sets the variables to the defaults.
  404. X
  405. XIFormat::IFormat()
  406. X{
  407. X    putseps = 1; // Should we use a separator
  408. X    width   = 0; // Width to output from 0, 2-  0=infinity
  409. X    use_si  = 1;
  410. X    right_adjust = 1;
  411. X    sep     = ',';
  412. X    sep_width = 3;
  413. X    mode    = ios::dec;
  414. X}
  415. X
  416. X// ============================================================
  417. X// Author      : Scott Kirkwood
  418. X// Date        : Mon Nov  2 1992
  419. X//
  420. X// Prototype   : iformat.h
  421. X// Description :
  422. X
  423. Xconst char *IFormat::Str(long num) {
  424. X    int neg = 0;
  425. X
  426. X    if (num < 0) {
  427. X        neg = 1;
  428. X        num = -num;
  429. X    }
  430. X    return Str((unsigned long)num, neg);
  431. X}
  432. X
  433. X// ============================================================
  434. X// Author      : Scott Kirkwood
  435. X// Date        : Tue Nov 10 1992
  436. X//
  437. X// Prototype   : iformat.h
  438. X// Description :
  439. X// Main routine, handles output of unsigned longs.
  440. X// Note: setting width to anything but 0 causes a big speed penalty.
  441. X//
  442. Xconst char *IFormat::Str(unsigned long num, int neg) {
  443. X    int as = 0;
  444. X    int old_putseps = putseps;
  445. X    // Commas will move the string to the right need 2 bytes for
  446. X    // the potential SI postfix and the null.
  447. X    char *last = str + sizeof(str) - IFormatMaxCommas - 2;
  448. X    char *first;
  449. X    int len = 0;
  450. X
  451. X    if (width) {
  452. X        if (use_si) {
  453. X            int tempwidth = width;
  454. X            register unsigned long tempnum = num;
  455. X            while (as < IFormatMAXSI - 1 && Size(tempnum, neg) > tempwidth) {
  456. X                if (as == 0)
  457. X                    tempwidth--; // because of the postfix character
  458. X                as++;
  459. X                tempnum = num / divby[as];
  460. X            }
  461. X            num = tempnum;
  462. X        }
  463. X        else {
  464. X            if (putseps && Size(num, neg) > width) {
  465. X                putseps = 0;
  466. X                if (Size(num, neg) > width)
  467. X                    putseps = old_putseps;
  468. X            }
  469. X        }
  470. X    }
  471. X    // The converter routines grows the string backwards from the least sig.
  472. X    // digit to the m.s. digit.  No null is placed.
  473. X    switch (mode) {
  474. X    case ios::hex:
  475. X        first = conv16(num, last, len);
  476. X        break;
  477. X    case ios::oct:
  478. X        first = conv8(num, last, len);
  479. X        break;
  480. X    default:
  481. X        first = uconv10(num, last, len);
  482. X        break;
  483. X    }
  484. X    last++;
  485. X    *last = 0;
  486. X    if (putseps)
  487. X        PutCommas(last, len);
  488. X
  489. X    if (neg) {
  490. X        first--;
  491. X        *first = '-';
  492. X        len++;
  493. X    }
  494. X
  495. X    if (width) {
  496. X        if (use_si && as) {
  497. X            *last++ = ext[as];
  498. X            *last   = 0;
  499. X            len++;
  500. X        }
  501. X        if (right_adjust)
  502. X            RightAdjust(first, len, width);
  503. X    }
  504. X    putseps = old_putseps;
  505. X    return first;
  506. X}
  507. X
  508. X// ============================================================
  509. X// Author      : Scott Kirkwood
  510. X// Date        : Mon Nov  2 1992
  511. X//
  512. X// Prototype   : iformat.h
  513. X// Description :
  514. X// Right adjust the string to the width specified.  Fill with spaces
  515. X// on the left.
  516. X
  517. Xvoid IFormat::RightAdjust(register char *&first, int len, int width)
  518. X{
  519. X    register int spaces = width - len;
  520. X    if (spaces < 1)
  521. X        return;
  522. X
  523. X    while (spaces--) {
  524. X        *--first = ' ';
  525. X    }
  526. X}
  527. X
  528. X// ============================================================
  529. X// Author      : Scott Kirkwood
  530. X// Date        : Mon Nov  2 1992
  531. X//
  532. X// Prototype   : iformat.h
  533. X// Description :
  534. X// Return the expected number of characters the number will take.
  535. X// Calculates the number of separators (commas) and the minus sign,
  536. X// but does not assume any postfix characters.
  537. X
  538. Xint IFormat::Size(register unsigned long num, int neg)
  539. X{
  540. X#ifdef REALLY_BIG
  541. X    static long arr[] = {1,10,100,1000,10000,100000,1000000,
  542. X      10000000,100000000,1000000000,10000000000,100000000000,
  543. X      1000000000000,10000000000000,100000000000000,
  544. X      1000000000000000,10000000000000000,100000000000000000,
  545. X      1000000000000000000,10000000000000000000};
  546. X#else
  547. X    static long arr[] = {1,10,100,1000,10000,100000,1000000,
  548. X    10000000,100000000,1000000000};
  549. X#endif
  550. X
  551. X    register len = 0;
  552. X    while (len < 10 && num > arr[len]) {
  553. X        len++;
  554. X    }
  555. X    if (len == 0)
  556. X        len = 1; // 0 = size 1;
  557. X
  558. X    // Ok, how many commas will be used for a string
  559. X    // of length len.
  560. X    if (len == 1)
  561. X        len = neg ? 2 : 1;
  562. X    else {
  563. X        // Count commas and possibly the minus sign
  564. X        if (putseps)
  565. X            len += ((len - 1) / sep_width) + (neg ? 1 : 0);
  566. X        else
  567. X            len += neg ? 1: 0;
  568. X    }
  569. X    return len;
  570. X}
  571. X
  572. X// ============================================================
  573. X// Author      : Scott Kirkwood
  574. X// Date        : Mon Nov  2 1992
  575. X//
  576. X// Prototype   : iformat.h
  577. X// Description :
  578. X// Put commas in the proper places.  Does this in place and therefore
  579. X// assumes that you have enough room in the string for the operation.
  580. X// Goes from right to left.
  581. X// P points to the null character.
  582. X
  583. Xvoid IFormat::PutCommas(char *&last, int &length)
  584. X{
  585. X    register int len = length;
  586. X    int count = 0;
  587. X
  588. X    // If length is <= sep_width then we don't need any stinking commas.
  589. X    if (len <= sep_width)
  590. X        return;
  591. X
  592. X    register char *p = last;
  593. X    int diff = (len - 1) / sep_width;
  594. X    length += diff;
  595. X    last   += diff;
  596. X    
  597. X    register char *g = p + diff;
  598. X
  599. X    count = sep_width;
  600. X    while (len--) {
  601. X        *g-- = *p--;
  602. X        if (count-- == 0 && *p != '-') {
  603. X            count = sep_width - 1;
  604. X            *g-- = sep;
  605. X        }
  606. X    }
  607. X}
  608. X
  609. X// ============================================================
  610. X// Author      : Scott Kirkwood
  611. X// Date        : Tue Nov 10 1992
  612. X//
  613. X// Prototype   : iformat.h
  614. X// Description :
  615. X// Sets the total format width, making sure it's not too big.
  616. Xvoid IFormat::SetWidth(int w) {
  617. X    if (w < IFormatMaxLen - 2) // null, and K not included
  618. X        width = w;
  619. X    else
  620. X        width = IFormatMaxLen - 2;
  621. X}
  622. X
  623. X
  624. X// ============================================================
  625. X// Author      : Scott Kirkwood
  626. X// Date        : Tue Nov 10 1992
  627. X//
  628. X// Prototype   : iformat.h
  629. X// Description :
  630. X// Sets the separation width making sure it's greater than or
  631. X// equal to 3.
  632. X
  633. Xvoid IFormat::SetSepWidth(int sw)
  634. X{
  635. X    if (sw < 3)
  636. X        sep_width = 3;
  637. X    else
  638. X        sep_width = sw;
  639. X}
  640. X
  641. X// ============================================================
  642. X// Author      : Scott Kirkwood
  643. X// Date        : Tue Nov 10 1992
  644. X//
  645. X// Prototype   : iformat.h
  646. X// Description :
  647. X// Set the SI postfix character (checks bounds)
  648. X
  649. Xvoid IFormat::SetSI(int i, char c)
  650. X{
  651. X    if (i > 0 && i < IFormatMAXSI)
  652. X        IFormat::ext[i] = c;
  653. X}
  654. X
  655. X// ============================================================
  656. X// Author      : Scott Kirkwood
  657. X// Date        : Tue Nov 10 1992
  658. X//
  659. X// Prototype   : iformat.h
  660. X// Description :
  661. X// Set the SI representation (checks bounds)
  662. X
  663. Xvoid IFormat::SetSI(int i, unsigned long val)
  664. X{
  665. X
  666. X    if (i > 0 && i < IFormatMAXSI)
  667. X        IFormat::divby[i] = val;
  668. X}
  669. X
  670. Xstatic const char digit1[] = {
  671. X    '0','1','2','3','4','5','6','7','8','9',
  672. X    '0','1','2','3','4','5','6','7','8','9',
  673. X    '0','1','2','3','4','5','6','7','8','9',
  674. X    '0','1','2','3','4','5','6','7','8','9',
  675. X    '0','1','2','3','4','5','6','7','8','9',
  676. X    '0','1','2','3','4','5','6','7','8','9',
  677. X    '0','1','2','3','4','5','6','7','8','9',
  678. X    '0','1','2','3','4','5','6','7','8','9',
  679. X    '0','1','2','3','4','5','6','7','8','9',
  680. X    '0','1','2','3','4','5','6','7','8','9',
  681. X    };
  682. X
  683. Xstatic const char digit2[] = {
  684. X    '0','0','0','0','0','0','0','0','0','0',
  685. X    '1','1','1','1','1','1','1','1','1','1',
  686. X    '2','2','2','2','2','2','2','2','2','2',
  687. X    '3','3','3','3','3','3','3','3','3','3',
  688. X    '4','4','4','4','4','4','4','4','4','4',
  689. X    '5','5','5','5','5','5','5','5','5','5',
  690. X    '6','6','6','6','6','6','6','6','6','6',
  691. X    '7','7','7','7','7','7','7','7','7','7',
  692. X    '8','8','8','8','8','8','8','8','8','8',
  693. X    '9','9','9','9','9','9','9','9','9','9',
  694. X    };
  695. X
  696. X
  697. X// ============================================================
  698. X// Description :
  699. X// This routine converts the long unsigned number to decimal.
  700. X// The variable p points to RIGHT end of a buffer. Function uconv10 returns
  701. X// pointer to left end of converted number.  The buffer is
  702. X// is not 0 terminated.
  703. X
  704. Xchar* uconv10(unsigned long i, char* bufend, int &len)
  705. X{
  706. X    register unsigned long j = i;
  707. X    register char* p = bufend;
  708. X    register int diff;
  709. X
  710. X    len = 0;
  711. X    do {
  712. X        long register by100 = j/100;
  713. X        diff = (int)(j-100*by100);
  714. X        *p-- = digit1[diff];
  715. X        *p-- = digit2[diff];
  716. X        len += 2;
  717. X        j = by100;
  718. X    } while ( j > 0 );
  719. X    if ( diff<10 ) {
  720. X        ++p; //compensate for extra 0
  721. X        len--;
  722. X    }
  723. X    return p + 1;
  724. X}
  725. X
  726. X
  727. X// ============================================================
  728. X// Description :
  729. X// This one converts to octal.
  730. X
  731. Xchar* conv8(register unsigned long i, register char* p, register int &len)
  732. X{
  733. X    len = 0;
  734. X    do {
  735. X        *p-- = (char)('0' + i%8);
  736. X        len++;
  737. X    } while ( (i >>= 3) > 0 );
  738. X
  739. X    return p + 1;
  740. X}
  741. X
  742. X
  743. X// ============================================================
  744. X// Description :
  745. X// This routine converts to hexadecimal.
  746. X
  747. Xchar* conv16(register unsigned long i, register char* p, register int &len)
  748. X{
  749. X    len = 0;
  750. X    do {
  751. X        register dig = (int)(i%16);
  752. X
  753. X        if (dig < 10)
  754. X            *p-- = (char)('0' + i%16);
  755. X        else
  756. X            *p-- = (char)('A'-10 + dig);
  757. X        len++;
  758. X    } while ( (i >>= 4) > 0 );
  759. X
  760. X    return p + 1;
  761. X}
  762. END_OF_FILE
  763. if test 9885 -ne `wc -c <'iformat.C'`; then
  764.     echo shar: \"'iformat.C'\" unpacked with wrong size!
  765. fi
  766. # end of 'iformat.C'
  767. fi
  768. if test -f 'iformat.h' -a "${1}" != "-c" ; then 
  769.   echo shar: Will not clobber existing file \"'iformat.h'\"
  770. else
  771. echo shar: Extracting \"'iformat.h'\" \(4231 characters\)
  772. sed "s/^X//" >'iformat.h' <<'END_OF_FILE'
  773. X#ifndef _FORMAT_H
  774. X#define _FORMAT_H
  775. X// Copyright (C) 1992 Scott Kirkwood (Queen's University, Ontario, Canada)
  776. X// Voice phone : (613) 531-2674, internet: kirkwood@qucis.queensu.ca
  777. X// This program is given as freeware with no warantees.  Not liable for
  778. X// any loss or damage resulting from this code.  Please acknowledge authorship.
  779. X// Note: Tabs in are size 4
  780. X
  781. X
  782. X//Description
  783. X//===========
  784. X//
  785. X// IFormat is a C++ class that is designed to output formatted
  786. X// integers (int, long, etc.).  By formatted I mean:
  787. X//    1,234,567
  788. X//
  789. X// One of the main concerns of IFormat was to make it FAST.
  790. X// On some Unix machines using gcc and CC IFormat was between
  791. X// 50% to 200% faster than sprintf() -- and sprintf won't put in commas!
  792. X// With Borlands C++ v3 IFormat was 25% to 50% SLOWER.
  793. X// With gcc 2.2.2 on the PC IFormat about even with sprintf().
  794. X//
  795. X// OTHER FEATURES
  796. X// ==============
  797. X//
  798. X// IFormat can format to a specified total character width, if the
  799. X// number doesn't fit it will be divided down until it does and then
  800. X// the appropriate SI notation will be affixed.  For instance, if
  801. X// you gave IFormat the number 1234567 and set the width to 6 you would
  802. X// get:
  803. X//  1,234K           (note, it was truncated not rounded)
  804. X//
  805. X// By default the postfixes are K=1,000,  M=1,000,000,  G=1,000,000,000
  806. X// but you can change these values if you prefer the computer science
  807. X// K = 1,024, for instance.
  808. X//
  809. X// You can also have output in hexadecimal or octal.
  810. X//
  811. X// IFormat will, by default, right adjust number if the ouput is smaller
  812. X// than the width passed.  Where a width of 0 signifies variable width.
  813. X// For instance, here's 123 with a width of 5 (vertical bars for clarity)
  814. X//   |  123|
  815. X//
  816. X// You can toggle whether to use SI postfixes, right adjusting, and
  817. X// whether separators are used.
  818. X//
  819. X// The width must be less than or equal to 14 otherwise it will
  820. X// be ignored (unless you have BIG_NUMBERS set).
  821. X// Note: I have only tested this program with 4 byte longs.  If you
  822. X// have large longs #define BIG_NUMBERS and try it, but I'm not sure
  823. X// if it will work with larger longs (haven't tested it).
  824. X
  825. X#ifndef BIG_NUMBERS
  826. Xconst IFormatMAXSI = 4;
  827. Xconst IFormatMaxCommas = 3;
  828. Xconst IFormatMaxLen = 16; // including -, comma, K and null
  829. X#else
  830. Xconst IFormatMAXSI = 5;
  831. Xconst IFormatMaxCommas = 6;
  832. Xconst IFormatMaxLen = 29;
  833. X#endif
  834. X
  835. Xclass IFormat {
  836. X    char   sep;                // Usually a comma
  837. X    short  sep_width;          // Usually three
  838. X    static char ext[IFormatMAXSI];
  839. X    static unsigned long divby[IFormatMAXSI];
  840. X    char   str[IFormatMaxLen]; // string where I number is stored.
  841. X    int    putseps;            // Should we use a separator?
  842. X    int    right_adjust;       // Should we right adjust?
  843. X    int    use_si;             // Should we use SI postfix notations?
  844. X    int    width;              // Width to output from 0-(MaxLen - 2)
  845. X    int    mode;               // oct, hex or (default) dec.
  846. X
  847. X    void Show();
  848. X    void SetVars();
  849. X    int  Size(register unsigned long num, int neg);
  850. X    void PutCommas(char *&end, int &len);
  851. X    void KillDot(char *str);
  852. X    void RightAdjust(register char *&last, int len, int width);
  853. Xpublic:
  854. X    IFormat(); // Constructor
  855. X    
  856. X    const char *Str(int num)          { return Str((long)num); }
  857. X    const char *Str(long num);
  858. X    const char *Str(unsigned int num) { return Str((long)num); }
  859. X    const char *Str(unsigned long num, int neg = 0);
  860. X    const char *Str(char num)         { return Str((long)num); }
  861. X    void  SetSepWidth(int i);
  862. X    void  SetWidth(int i);
  863. X    void  SetSep(char ch)             { sep = ch; }
  864. X    void  SetUseSeparators(int i)     { putseps = i; }
  865. X    void  SetRightAdjust(int i)       { right_adjust = i; }
  866. X    void  SetUseSI(int i)             { use_si = i; }
  867. X    // use SetMode(ios::hex or ios::dec or ios::oct)
  868. X    void  SetMode(int i)              { mode = i; }
  869. X    void  SetSI(int i, char c);            // set SI character ex. i=1 ->'K'
  870. X    void  SetSI(int i, unsigned long val); // Set SI value     ex. i=1->1000
  871. X    int   SepWidth()                  { return sep_width; }
  872. X    int   Width()                     { return width; }
  873. X    char  Sep()                       { return sep; }
  874. X    int   UseSeparators()             { return putseps; }
  875. X    int   RightAdjust()               { return right_adjust; }
  876. X    int   UseSI()                     { return use_si; }
  877. X};
  878. X
  879. X#endif
  880. END_OF_FILE
  881. if test 4231 -ne `wc -c <'iformat.h'`; then
  882.     echo shar: \"'iformat.h'\" unpacked with wrong size!
  883. fi
  884. # end of 'iformat.h'
  885. fi
  886. if test -f 'make.bor' -a "${1}" != "-c" ; then 
  887.   echo shar: Will not clobber existing file \"'make.bor'\"
  888. else
  889. echo shar: Extracting \"'make.bor'\" \(886 characters\)
  890. sed "s/^X//" >'make.bor' <<'END_OF_FILE'
  891. X.AUTODEPEND
  892. X
  893. X#        *Translator Definitions*
  894. XCC = bcc +IFORMAT.CFG
  895. XTASM = TASM
  896. XTLIB = tlib
  897. XTLINK = tlink
  898. XLIBPATH = C:\BC3\LIB
  899. XINCLUDEPATH = C:\BC3\INCLUDE
  900. X
  901. X
  902. X#        *Implicit Rules*
  903. X.c.obj:
  904. X  $(CC) -c {$< }
  905. X
  906. X.cpp.obj:
  907. X  $(CC) -c {$< }
  908. X
  909. X#        *List Macros*
  910. X
  911. X
  912. XEXE_dependencies =  \
  913. X iformat.obj \
  914. X test.obj
  915. X
  916. X#        *Explicit Rules*
  917. Xiformat.exe: iformat.cfg $(EXE_dependencies)
  918. X  $(TLINK) /v/x/c/P-/L$(LIBPATH) @&&|
  919. Xc0s.obj+
  920. Xiformat.obj+
  921. Xtest.obj
  922. Xiformat
  923. X        # no map file
  924. Xcs.lib
  925. X|
  926. X
  927. X
  928. X#        *Individual File Dependencies*
  929. Xiformat.obj: iformat.cfg iformat.cc
  930. X    $(CC) -c iformat.cc
  931. X
  932. Xtest.obj: iformat.cfg test.cc
  933. X    $(CC) -c test.cc
  934. X
  935. X#        *Compiler Configuration File*
  936. Xiformat.cfg: iformat.mak
  937. X  copy &&|
  938. X-f-
  939. X-ff-
  940. X-G
  941. X-O
  942. X-Og
  943. X-Oe
  944. X-Om
  945. X-Ov
  946. X-Ol
  947. X-Ob
  948. X-Op
  949. X-Oi
  950. X-Z
  951. X-k-
  952. X-vi
  953. X-w-ret
  954. X-w-nci
  955. X-w-inl
  956. X-w-par
  957. X-w-cpt
  958. X-w-dup
  959. X-w-pia
  960. X-w-ill
  961. X-w-sus
  962. X-w-ext
  963. X-w-ias
  964. X-w-ibc
  965. X-w-pre
  966. X-w-nst
  967. X-I$(INCLUDEPATH)
  968. X-L$(LIBPATH)
  969. X-DSPEED
  970. X-P
  971. X| iformat.cfg
  972. X
  973. X
  974. END_OF_FILE
  975. if test 886 -ne `wc -c <'make.bor'`; then
  976.     echo shar: \"'make.bor'\" unpacked with wrong size!
  977. fi
  978. # end of 'make.bor'
  979. fi
  980. if test -f 'my.out' -a "${1}" != "-c" ; then 
  981.   echo shar: Will not clobber existing file \"'my.out'\"
  982. else
  983. echo shar: Extracting \"'my.out'\" \(2529 characters\)
  984. sed "s/^X//" >'my.out' <<'END_OF_FILE'
  985. XDefault.
  986. X|Unlimited|
  987. X|1|
  988. X|12|
  989. X|123|
  990. X|1,234|
  991. X|12,345|
  992. X|123,456|
  993. X|1,234,567|
  994. X|12,345,678|
  995. X|123,456,789|
  996. X|1,234,567,890|
  997. X|2,147,483,647| (LONG_MAX)
  998. X|0| (ZERO)
  999. X|-1|
  1000. X|-12|
  1001. X|-123|
  1002. X|-1,234|
  1003. X|-12,345|
  1004. X|-123,456|
  1005. X|-1,234,567|
  1006. X|-12,345,678|
  1007. X|-123,456,789|
  1008. X|-1,234,567,890|
  1009. X|-2,147,483,648| (LONG_MIN)
  1010. XDon't use the separators.
  1011. X|Unlimited|
  1012. X|1|
  1013. X|12|
  1014. X|123|
  1015. X|1234|
  1016. X|12345|
  1017. X|123456|
  1018. X|1234567|
  1019. X|12345678|
  1020. X|123456789|
  1021. X|1234567890|
  1022. X|2147483647| (LONG_MAX)
  1023. X|0| (ZERO)
  1024. X|-1|
  1025. X|-12|
  1026. X|-123|
  1027. X|-1234|
  1028. X|-12345|
  1029. X|-123456|
  1030. X|-1234567|
  1031. X|-12345678|
  1032. X|-123456789|
  1033. X|-1234567890|
  1034. X|-2147483648| (LONG_MIN)
  1035. XSet width to 7 and don't right adjust.
  1036. X|-------|
  1037. X|1|
  1038. X|12|
  1039. X|123|
  1040. X|1,234|
  1041. X|12,345|
  1042. X|123,456|
  1043. X|1,234K|
  1044. X|12,345K|
  1045. X|123M|
  1046. X|1,234M|
  1047. X|2,147M| (LONG_MAX)
  1048. X|0| (ZERO)
  1049. X|-1|
  1050. X|-12|
  1051. X|-123|
  1052. X|-1,234|
  1053. X|-12,345|
  1054. X|-123K|
  1055. X|-1,234K|
  1056. X|-12M|
  1057. X|-123M|
  1058. X|-1,234M|
  1059. X|-2,147M| (LONG_MIN)
  1060. XSet width to 7 and don't use SI.
  1061. X|-------|
  1062. X|      1|
  1063. X|     12|
  1064. X|    123|
  1065. X|  1,234|
  1066. X| 12,345|
  1067. X|123,456|
  1068. X|1234567|
  1069. X|12,345,678|
  1070. X|123,456,789|
  1071. X|1,234,567,890|
  1072. X|2,147,483,647| (LONG_MAX)
  1073. X|      0| (ZERO)
  1074. X|     -1|
  1075. X|    -12|
  1076. X|   -123|
  1077. X| -1,234|
  1078. X|-12,345|
  1079. X|-123456|
  1080. X|-1,234,567|
  1081. X|-12,345,678|
  1082. X|-123,456,789|
  1083. X|-1,234,567,890|
  1084. X|-2,147,483,648| (LONG_MIN)
  1085. XSet separator width to 4 and Sep is a space.
  1086. X|Unlimited|
  1087. X|1|
  1088. X|12|
  1089. X|123|
  1090. X|1234|
  1091. X|1 2345|
  1092. X|12 3456|
  1093. X|123 4567|
  1094. X|1234 5678|
  1095. X|1 2345 6789|
  1096. X|12 3456 7890|
  1097. X|21 4748 3647| (LONG_MAX)
  1098. X|0| (ZERO)
  1099. X|-1|
  1100. X|-12|
  1101. X|-123|
  1102. X|-1234|
  1103. X|-1 2345|
  1104. X|-12 3456|
  1105. X|-123 4567|
  1106. X|-1234 5678|
  1107. X|-1 2345 6789|
  1108. X|-12 3456 7890|
  1109. X|-21 4748 3648| (LONG_MIN)
  1110. XNormal SepWidth, but Width set to 5
  1111. X|-----|
  1112. X|    1|
  1113. X|   12|
  1114. X|  123|
  1115. X|1,234|
  1116. X|  12K|
  1117. X| 123K|
  1118. X|   1M|
  1119. X|  12M|
  1120. X| 123M|
  1121. X|   1G|
  1122. X|   2G| (LONG_MAX)
  1123. X|    0| (ZERO)
  1124. X|   -1|
  1125. X|  -12|
  1126. X| -123|
  1127. X|  -1K|
  1128. X| -12K|
  1129. X|-123K|
  1130. X|  -1M|
  1131. X| -12M|
  1132. X|-123M|
  1133. X|  -1G|
  1134. X|  -2G| (LONG_MIN)
  1135. XWidth set to 5 and don't use seps.
  1136. X|-----|
  1137. X|    1|
  1138. X|   12|
  1139. X|  123|
  1140. X| 1234|
  1141. X|12345|
  1142. X| 123K|
  1143. X|1234K|
  1144. X|  12M|
  1145. X| 123M|
  1146. X|1234M|
  1147. X|2147M| (LONG_MAX)
  1148. X|    0| (ZERO)
  1149. X|   -1|
  1150. X|  -12|
  1151. X| -123|
  1152. X|-1234|
  1153. X| -12K|
  1154. X|-123K|
  1155. X|  -1M|
  1156. X| -12M|
  1157. X|-123M|
  1158. X|  -1G|
  1159. X|  -2G| (LONG_MIN)
  1160. XDifferent widths
  1161. X================
  1162. X|-2,147,483,648| width = 0
  1163. X|-2G| width = 1
  1164. X|-2G| width = 2
  1165. X|-2G| width = 3
  1166. X| -2G| width = 4
  1167. X|  -2G| width = 5
  1168. X|   -2G| width = 6
  1169. X|-2,147M| width = 7
  1170. X| -2,147M| width = 8
  1171. X|  -2,147M| width = 9
  1172. X|   -2,147M| width = 10
  1173. X|-2,147,483K| width = 11
  1174. X| -2,147,483K| width = 12
  1175. X|  -2,147,483K| width = 13
  1176. X|-2,147,483,648| width = 14
  1177. X|-2,147,483,648| max width
  1178. XTesting type long.
  1179. X12,345
  1180. XTesting type unsigned long.
  1181. X12,345
  1182. XTesting type int.
  1183. X12,345
  1184. XTesting type unsigned int.
  1185. X12,345
  1186. XTesting type char.
  1187. X65
  1188. END_OF_FILE
  1189. if test 2529 -ne `wc -c <'my.out'`; then
  1190.     echo shar: \"'my.out'\" unpacked with wrong size!
  1191. fi
  1192. # end of 'my.out'
  1193. fi
  1194. if test -f 'test.C' -a "${1}" != "-c" ; then 
  1195.   echo shar: Will not clobber existing file \"'test.C'\"
  1196. else
  1197. echo shar: Extracting \"'test.C'\" \(6413 characters\)
  1198. sed "s/^X//" >'test.C' <<'END_OF_FILE'
  1199. X// Copyright (C) 1992 Scott Kirkwood (Queen's University, Ontario, Canada)
  1200. X// Voice phone : (613) 531-2674, internet: kirkwood@qucis.queensu.ca
  1201. X// This program is given as freeware with no warantees.  Not liable for
  1202. X// any loss or damage resulting from this code.  Please acknowledge authorship.
  1203. X// Note: Tabs in are size 4
  1204. X
  1205. X// This program is a test suite for the IFormat C++ class.
  1206. X
  1207. X#include <iostream.h>
  1208. X#include "iformat.h"
  1209. X#include <time.h>
  1210. X#include <stdio.h>
  1211. X#include <limits.h>
  1212. X
  1213. X// Function prototypes
  1214. X
  1215. Xvoid test_switches(int mode);
  1216. Xvoid show_width(int width);
  1217. Xvoid speed_test();
  1218. Xvoid type_test();
  1219. Xvoid other_test();
  1220. X
  1221. Xint main(int argc, char **argv)
  1222. X{
  1223. X    if (argc == 2) {
  1224. X        speed_test();
  1225. X    }
  1226. X    else {
  1227. X        test_switches(ios::dec);
  1228. X        //      test_switches(ios::hex);
  1229. X        //      test_switches(ios::oct);
  1230. X
  1231. X        other_test();
  1232. X        type_test();
  1233. X    }
  1234. X
  1235. X    return 0;
  1236. X}
  1237. X
  1238. X#ifndef __TURBOC__
  1239. X#include <sys/time.h>
  1240. X#include <sys/resource.h>
  1241. Xinline    unsigned long CLOCK() {
  1242. X        struct rusage RU;
  1243. X            
  1244. X        getrusage(RUSAGE_SELF,&RU);
  1245. X        return RU.ru_utime.tv_sec * 1000000UL + RU.ru_utime.tv_usec;
  1246. X    }
  1247. X#else
  1248. Xinline long CLOCK() { return clock(); }
  1249. X#endif
  1250. X
  1251. Xvoid speed_test() {
  1252. X#ifdef __TURBOC__
  1253. X    const long factor = 5;
  1254. X    const char *mes = " clock ticks.";
  1255. X#else
  1256. X    const char *mes = " micro-seconds.";
  1257. X    const long factor = -5;
  1258. X#endif
  1259. X    unsigned long iter;
  1260. X    unsigned long time_start;
  1261. X    register unsigned long int i;
  1262. X    char work[81];
  1263. X
  1264. X    cout << "Performing speed check please wait..." << endl;
  1265. X    // Let's do a quick and dirty speed check
  1266. X    long speed = 0;
  1267. X
  1268. X    time_start = time(0);
  1269. X    while (time(0) == time_start) // sychronize on clock edge
  1270. X        ;
  1271. X    time_start = time(0) + 1;
  1272. X    while (time(0) < time_start)
  1273. X        speed++;
  1274. X
  1275. X    if (factor < 0)
  1276. X        iter = speed / (-factor);
  1277. X    else
  1278. X        iter = speed * factor;
  1279. X
  1280. X
  1281. X    IFormat a, b;
  1282. X    a.SetWidth(2);
  1283. X
  1284. X    cout << "Performing tests (loops of " << b.Str(iter) << 
  1285. X        " iterations) ..." << endl;
  1286. X    time_start = CLOCK();
  1287. X
  1288. X    for (i = 0; i < iter; i++) {
  1289. X        a.Str(LONG_MAX);
  1290. X    }
  1291. X
  1292. X    long time_worst = CLOCK() - time_start;
  1293. X    cout << "IFormat (worst case)      : " << b.Str(time_worst) <<
  1294. X        mes << endl;
  1295. X    cout << "Sample:" << a.Str(LONG_MAX) << endl;
  1296. X    a.SetWidth(0);
  1297. X
  1298. X    time_start = CLOCK();
  1299. X
  1300. X    for (i = 0; i < iter; i++) {
  1301. X        a.Str(123456);
  1302. X    }
  1303. X
  1304. X    long time_avg = CLOCK() - time_start;
  1305. X    cout << "IFormat (avg case)        : " << b.Str(time_avg) <<
  1306. X        mes << endl;
  1307. X    cout << "Sample:" << a.Str(123456) << endl;
  1308. X
  1309. X    a.SetUseSeparators(0);
  1310. X    a.SetRightAdjust(0);
  1311. X    a.SetUseSI(0);
  1312. X
  1313. X    time_start = CLOCK();
  1314. X
  1315. X    for (i = 0; i < iter; i++) {
  1316. X        a.Str(123456);
  1317. X    }
  1318. X    long time_best = CLOCK() - time_start;
  1319. X    cout << "IFormat (best case)       : " << b.Str(time_best) <<
  1320. X        mes << endl;
  1321. X    cout << "Sample:" << a.Str(123456) << endl;
  1322. X
  1323. X    time_start = CLOCK();
  1324. X
  1325. X    for (i = 0; i < iter; i++) {
  1326. X        sprintf(work,"%li", 123456L);
  1327. X    }
  1328. X
  1329. X    long time_sprintf = CLOCK() - time_start;
  1330. X    cout << "Sprintf (fast)            : " << b.Str(time_sprintf) <<
  1331. X        mes << endl;
  1332. X    cout << "Sample:" << work << endl;
  1333. X
  1334. X    time_start = CLOCK();
  1335. X
  1336. X    for (i = 0; i < iter; i++) {
  1337. X        sprintf(work, "%7li", 123456L);
  1338. X    }
  1339. X    long time_sprintf_slow = CLOCK() - time_start;
  1340. X    cout << "Sprintf (width specified) : " << b.Str(time_sprintf_slow) <<
  1341. X        mes << endl;
  1342. X    cout << "Sample:" << work << endl;
  1343. X
  1344. X
  1345. X    cout << "IFormat is between ";
  1346. X    if (time_worst)
  1347. X        cout << (100 * time_sprintf / time_worst) - 100;
  1348. X    else
  1349. X        cout << "more than " << (time_sprintf * 100) - 100;
  1350. X    cout << "% and ";
  1351. X    if (time_best)
  1352. X        cout << (100 * time_sprintf_slow / time_best) - 100;
  1353. X    else
  1354. X        cout << "more than " << (time_sprintf_slow * 100) - 100;
  1355. X
  1356. X    cout << "% faster than sprintf." << endl;
  1357. X    cout << "Negative numbers mean it's slower." << endl;
  1358. X}
  1359. X
  1360. Xvoid test_switches(int mode)
  1361. X{
  1362. X    long l;
  1363. X
  1364. X    for (int j = 0; j <= 6; j++) {
  1365. X        IFormat a;
  1366. X
  1367. X        a.SetMode(mode);
  1368. X        switch (j) {
  1369. X        case 0:
  1370. X            cout << "Default." << endl;
  1371. X            break;
  1372. X        case 1:
  1373. X            cout << "Don't use the separators." << endl;
  1374. X            a.SetUseSeparators(0);
  1375. X            break;
  1376. X        case 2: {
  1377. X            const width2 = 7;
  1378. X            cout << "Set width to " << width2 <<
  1379. X                " and don't right adjust." << endl;
  1380. X            a.SetWidth(width2);
  1381. X            a.SetRightAdjust(0);
  1382. X        }       break;
  1383. X        case 3: {
  1384. X            const width3 = 7;
  1385. X            cout << "Set width to " << width3 <<
  1386. X                " and don't use SI." << endl;
  1387. X            a.SetWidth(width3);
  1388. X            a.SetUseSI(0);
  1389. X        }       break;
  1390. X        case 4: {
  1391. X            const sepw4 = 4;
  1392. X            cout << "Set separator width to " << sepw4 <<
  1393. X                " and Sep is a space." << endl;
  1394. X
  1395. X            a.SetSep(' ');
  1396. X            a.SetSepWidth(sepw4);
  1397. X        }       break;
  1398. X        case 5: {
  1399. X            const width5 = 5;
  1400. X            cout << "Normal SepWidth, but Width set to " << width5 << endl;
  1401. X            a.SetWidth(width5);
  1402. X        }       break;
  1403. X        case 6: {
  1404. X            const width6 = 5;
  1405. X            cout << "Width set to " << width6 << " and don't use seps." << endl;
  1406. X            a.SetWidth(width6);
  1407. X            a.SetUseSeparators(0);
  1408. X        }       break;
  1409. X        }
  1410. X        l = 1;
  1411. X        show_width(a.Width());
  1412. X        for (int i = 0; i < 10; i++) {
  1413. X            cout << "|" << a.Str(l) << "|" << endl;
  1414. X            switch (mode) {
  1415. X            default: // ios::dec
  1416. X                l *= 10;
  1417. X                l += (i + 2) % 10;
  1418. X                break;
  1419. X            case ios::hex:
  1420. X                l <<= 4;
  1421. X                l += (i + 2) % 16;
  1422. X                break;
  1423. X            case ios::oct:
  1424. X                l <<= 3;
  1425. X                l += (i + 2) % 8;
  1426. X                break;
  1427. X            }
  1428. X        }
  1429. X        l = -1;
  1430. X        cout << "|" << a.Str(LONG_MAX) << "| (LONG_MAX)" << endl;
  1431. X        cout << "|" << a.Str(0) << "| (ZERO)" << endl;
  1432. X
  1433. X        for (i = 0; i < 10; i++) {
  1434. X            cout << "|" <<  a.Str(l) << "|" << endl;
  1435. X            switch (mode) {
  1436. X            default: // ios::dec
  1437. X                l *= 10;
  1438. X                l -= (i + 2) % 10;
  1439. X                break;
  1440. X            case ios::hex:
  1441. X                l <<= 4;
  1442. X                l -= (i + 2) % 16;
  1443. X                break;
  1444. X            case ios::oct:
  1445. X                l <<= 3;
  1446. X                l -= (i + 2) % 8;
  1447. X                break;
  1448. X            }
  1449. X        }
  1450. X        cout << "|" << a.Str(LONG_MIN) << "| (LONG_MIN)" << endl;
  1451. X    }
  1452. X}
  1453. X
  1454. Xvoid show_width(int width)
  1455. X{
  1456. X    int i;
  1457. X
  1458. X    cout << '|';
  1459. X    if (width) {
  1460. X        for (i = 0; i < width; i++)
  1461. X            cout << '-';
  1462. X    }
  1463. X    else {
  1464. X        cout << "Unlimited";
  1465. X    }
  1466. X    cout << '|' << endl;;
  1467. X}
  1468. X
  1469. Xvoid type_test() {
  1470. X    IFormat a;
  1471. X    cout << "Testing type long." << endl;
  1472. X    cout << a.Str(12345L) << endl;
  1473. X    cout << "Testing type unsigned long."  << endl;
  1474. X    cout << a.Str(12345UL) << endl;
  1475. X    cout << "Testing type int." << endl;
  1476. X    cout << a.Str(12345) << endl;
  1477. X    cout << "Testing type unsigned int." << endl;
  1478. X    cout << a.Str(12345U) << endl;
  1479. X    cout << "Testing type char." << endl;
  1480. X    cout << a.Str('A') << endl;
  1481. X}
  1482. X
  1483. Xvoid other_test() {
  1484. X    IFormat a;
  1485. X    cout << "Different widths" << endl;
  1486. X    cout << "================" << endl;
  1487. X    for (int i = 0; i < IFormatMaxLen - 1; i++) {
  1488. X        a.SetWidth(i);
  1489. X        cout << '|' << a.Str(LONG_MIN) << "| width = " << i << endl;
  1490. X    }
  1491. X    a.SetWidth(999);
  1492. X    cout << '|' << a.Str(LONG_MIN) << "| max width" << endl;
  1493. X}
  1494. END_OF_FILE
  1495. if test 6413 -ne `wc -c <'test.C'`; then
  1496.     echo shar: \"'test.C'\" unpacked with wrong size!
  1497. fi
  1498. # end of 'test.C'
  1499. fi
  1500. if test -f 'test.bat' -a "${1}" != "-c" ; then 
  1501.   echo shar: Will not clobber existing file \"'test.bat'\"
  1502. else
  1503. echo shar: Extracting \"'test.bat'\" \(219 characters\)
  1504. sed "s/^X//" >'test.bat' <<'END_OF_FILE'
  1505. X@echo on
  1506. Xrem set prog=go32 test
  1507. Xset prog=iformat
  1508. Xecho Renaming all *.c to *.cc
  1509. Xren *.c *.cc
  1510. Xecho Test routine for IFormat - should read "FC: no differences encountered"
  1511. X%prog% > your.out
  1512. Xfc my.out your.out
  1513. X%prog% speed
  1514. END_OF_FILE
  1515. if test 219 -ne `wc -c <'test.bat'`; then
  1516.     echo shar: \"'test.bat'\" unpacked with wrong size!
  1517. fi
  1518. # end of 'test.bat'
  1519. fi
  1520. if test -f 'test.sh' -a "${1}" != "-c" ; then 
  1521.   echo shar: Will not clobber existing file \"'test.sh'\"
  1522. else
  1523. echo shar: Extracting \"'test.sh'\" \(387 characters\)
  1524. sed "s/^X//" >'test.sh' <<'END_OF_FILE'
  1525. X#!/bin/sh
  1526. X## Test routine for IFormat
  1527. X
  1528. Xmake test
  1529. Xiformat > your.out
  1530. Xlines=`diff my.out your.out | wc -l`
  1531. Xif (test $lines -ne 0) then
  1532. X    echo "Hmm. your output is different then my output"
  1533. X    echo "Here's what diff gave me"
  1534. X    echo "diff my.out your.out"
  1535. X    diff my.out your.out
  1536. Xelse
  1537. X    iformat | more
  1538. X    echo 'Passed test'
  1539. Xfi
  1540. Xecho "Speed test"
  1541. Xecho "=========="
  1542. Xecho "Please wait..."
  1543. Xiformat speed 
  1544. END_OF_FILE
  1545. if test 387 -ne `wc -c <'test.sh'`; then
  1546.     echo shar: \"'test.sh'\" unpacked with wrong size!
  1547. fi
  1548. chmod +x 'test.sh'
  1549. # end of 'test.sh'
  1550. fi
  1551. echo shar: End of archive 1 \(of 1\).
  1552. cp /dev/null ark1isdone
  1553. MISSING=""
  1554. for I in 1 ; do
  1555.     if test ! -f ark${I}isdone ; then
  1556.     MISSING="${MISSING} ${I}"
  1557.     fi
  1558. done
  1559. if test "${MISSING}" = "" ; then
  1560.     echo You have the archive.
  1561.     rm -f ark[1-9]isdone
  1562. else
  1563.     echo You still need to unpack the following archives:
  1564.     echo "        " ${MISSING}
  1565. fi
  1566. ##  End of shell archive.
  1567. exit 0
  1568. -- 
  1569. -------------------- kirkwood@qucis.queensu.ca ----------------------
  1570.       299,792,458 m/s it's not just a good idea, it's the law!
  1571.  
  1572.  
  1573. exit 0 # Just in case...
  1574.