home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c221 / 2.ddi / DOC / TOOLS4_1.DOC next >
Encoding:
Text File  |  1992-04-01  |  258.8 KB  |  9,280 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12.  
  13.  
  14.  
  15.  
  16.                                        Rogue Wave
  17.  
  18.                                         Tools.h++
  19.  
  20.                                       Class Library
  21.  
  22.                                        Version 4.0
  23.  
  24.  
  25.  
  26.  
  27.  
  28.  
  29.  
  30.  
  31.  
  32.  
  33.  
  34.  
  35.                                License Agreement
  36.  
  37.              c Copyright Rogue Wave Associates, 1989, 1990, 1991.
  38.  
  39.  
  40. This software package and its documentation are subject to the
  41. following license agreement.  By opening the diskette package seal,
  42. you are implicitly accepting these terms and conditions.
  43.  
  44. Permission is given to the buyer of this package to use this software
  45. on one computer at a time, make one backup copy, and make one printed
  46. copy of the source code.  You may utilize and/or modify this program
  47. for use in your projects.  You may distribute and sell any executable
  48. which results from using this code in your applications, except a
  49. utility program of similar nature to this product.  You may NOT
  50. redistribute the source code or resultant object modules or libraries
  51. of object modules in any form, put it on a bulletin board system, or
  52. sell it.  You may not use, copy, modify, merge, or transfer the
  53. program, or manual or any portion of the program or manual, except as
  54. expressly provided above in this agreement.
  55.  
  56. A multi-user license may be purchased to allow the software to be
  57. used on more than one computer at the same time; including a shared
  58. disk system.  Contact Rogue Wave for information on site licenses.
  59.  
  60. This material is sold "as is". Rogue Wave makes no warranties, either
  61. expressed or implied, regarding the enclosed computer software
  62. package, its merchantability, or its fitness for any particular
  63. purpose. Information in this document is subject to change without
  64. notice and does not represent a commitment on the part of Rogue Wave
  65. .  While every effort is made to insure that the above mentioned
  66. product and its documentation are free of defects, Rogue Wave shall
  67. not be held responsible for any loss of profit or any other
  68. commercial damage, including but not limited to special, incidental,
  69. consequential or other damages occasioned by the use of this product.
  70.  
  71. It is assumed that purchasers of this product are familiar with basic
  72. programming skills (e.g., setting up a path with MS-DOS). This is a
  73. highly technical product, offered in a rapidly evolving programming
  74. environment. Rogue Wave recognizes this fact, and will provide
  75. limited support to purchasers of this product for 60 days after its
  76. purchase (of course, bug reports and comments are always welcome).
  77. Questions and comments may be submitted either by mail or telephone.
  78. Rogue Wave reserves the right to respond to questions or comments in
  79. writing or by telephone.
  80.  
  81.  
  82.  
  83.  
  84.  
  85.  
  86.  
  87.  
  88.  
  89.  
  90.  
  91. Rogue Wave acknowledges all trademarks found in this manual and in the source
  92. code documentation.  This acknowledgement includes, but is not limited to:
  93. AT&T/UNIX, Microsoft, MS-DOS, Zortech, Borland, Oregon Software, HCR,
  94. ParcPlace, Smalltalk-80, SCO, Free Software Foundation, Glockenspiel, 
  95. Windows.
  96.  
  97.  
  98.  
  99.  
  100.  
  101.  
  102.  
  103.  
  104.  
  105.  
  106.                                     Table of Contents
  107.  
  108.                                          PART I
  109.  
  110.  
  111. 1. Introduction....................................................1
  112.      1.1  Overview and features....................................1
  113.      1.2  Supported compilers......................................4
  114.      1.3  Philosophy   ............................................4
  115.      1.4  Conventions  ............................................5
  116.      1.5  Reading this manual......................................6
  117.  
  118. 2. Installation....................................................9
  119.      2.1  Installation overview....................................9
  120.           2.2       Installation: MS-DOS..........................11
  121.           2.2.1     Installation: Zortech.........................13
  122.           2.2.2     Installation: Glockenspiel....................13
  123.      2.3  Recompiling the library: MS-DOS.........................14
  124.           2.3.1     Borland.......................................15
  125.           2.3.2     Zortech.......................................16
  126.           2.3.3     Glockenspiel..................................17
  127.      2.4  Recompiling and installation: Unix......................17
  128.           2.4.1     AT&T..........................................19
  129.           2.4.2     Oregon Software...............................19
  130.           2.4.3     All Unix compilers............................19
  131.      2.5  Working with the Rogue Wave Math.h++ library............20
  132.      2.6  Recompiling the library: Creating a debug version.......20
  133.  
  134. 3.  Compiling Programs............................................21
  135.      3.1  Header files ...........................................21
  136.      3.2  Compiling a program.....................................25
  137.           3.2.1     Compiling a program: DOS......................26
  138.                3.2.1.1 Compiling a program: Borland ..............26
  139.                3.2.1.2 Using the Tools.h++ DLL with Borland C++ ..26
  140.                3.2.1.3 Compiling a program: Zortech ..............27
  141.                3.2.1.4 Compiling a program: Glockenspiel .........29
  142.           3.2.2     Compiling a program: Unix.....................29
  143.                3.2.2.1 Compiling a program: AT&T .................29
  144.  
  145. 4. Stream I/O.....................................................31
  146.  
  147. 5. Class Overview.................................................33
  148.  
  149.  
  150. Rogue Wave     Tools.h++ Class Library                i
  151.  
  152.  
  153.  
  154.  
  155.  
  156.  
  157.  
  158.  
  159.  
  160.  
  161.      5.1  Common member functions.................................34
  162.  
  163.  
  164.  
  165.  
  166.  
  167.  
  168.  
  169.  
  170.  
  171.  
  172.  
  173.  
  174.  
  175.  
  176.  
  177.  
  178.  
  179.  
  180.  
  181.  
  182.  
  183.  
  184.  
  185.  
  186.  
  187.  
  188.  
  189.  
  190.  
  191.  
  192.  
  193.  
  194.  
  195.  
  196.  
  197.  
  198.  
  199.  
  200.  
  201.  
  202.  
  203.  
  204.  
  205. Rogue Wave     Tools.h++ Class Library               ii
  206.  
  207.  
  208.  
  209.  
  210.  
  211.  
  212.  
  213.  
  214.  
  215.  
  216.  
  217. 6. Using Class RWString...........................................39
  218.      6.1  Example      ...........................................39
  219.      6.2  Reference counting......................................40
  220.      6.3  Member functions........................................43
  221.      6.4  SubStrings:  ...........................................44
  222.      6.5  Pattern matching........................................44
  223.           6.5.1     Regular expressions...........................45
  224.      6.6  Tokenizer    ...........................................47
  225.  
  226. 7. Using Class RWDate.............................................49
  227.      7.1  Constructors ...........................................49
  228.      7.2  Member functions........................................50
  229.      7.3  Example      ...........................................50
  230.  
  231. 8. Using Class RWTime.............................................51
  232.      8.1  Setting the time zone...................................51
  233.      8.2  Constructors ...........................................53
  234.      8.3  Member functions........................................53
  235.  
  236. 9. Virtual Streams................................................55
  237.      9.1  Specializing virtual streams............................58
  238.      9.2  Simple example..........................................58
  239.      9.3  Windows_ Clipboard and DDE streambufs...................61
  240.      9.4  DDE example  ...........................................61
  241.      9.5  Recap        ...........................................63
  242.  
  243. 10. Using Class RWFile............................................65
  244.      10.1 Example      ...........................................65
  245.  
  246. 11. Using Class RWFileManager.....................................67
  247.      11.1 Construction ...........................................67
  248.      11.2 Member functions........................................68
  249.  
  250. 12. Using Class RWBTreeOnDisk.....................................73
  251.      12.1 Construction ...........................................75
  252.      12.2 Example      ...........................................75
  253.  
  254. 13. Introduction to Collection Classes............................79
  255.      13.1 Introduction ...........................................79
  256.           13.1.1    Some general concepts.........................79
  257.                13.1.1.1An object's identity ......................80
  258.  
  259.  
  260. Rogue Wave     Tools.h++ Class Library              iii
  261.  
  262.  
  263.  
  264.  
  265.  
  266.  
  267.  
  268.  
  269.  
  270.  
  271.                13.1.1.2Shallow versus deep copies ................82
  272.  
  273.  
  274.  
  275.  
  276.  
  277.  
  278.  
  279.  
  280.  
  281.  
  282.  
  283.  
  284.  
  285.  
  286.  
  287.  
  288.  
  289.  
  290.  
  291.  
  292.  
  293.  
  294.  
  295.  
  296.  
  297.  
  298.  
  299.  
  300.  
  301.  
  302.  
  303.  
  304.  
  305.  
  306.  
  307.  
  308.  
  309.  
  310.  
  311.  
  312.  
  313.  
  314.  
  315. Rogue Wave     Tools.h++ Class Library               iv
  316.  
  317.  
  318.  
  319.  
  320.  
  321.  
  322.  
  323.  
  324.  
  325.  
  326.  
  327. 14. "Generic" Collection Classes..................................85
  328.      14.1 Example      ...........................................86
  329.      14.2 Declaring generic collection classes....................88
  330.      14.3 User-defined functions..................................88
  331.           14.3.1    Tester functions..............................89
  332.           14.3.2    Apply functions...............................92
  333.  
  334. 15. Smalltalk_-like Collection Classes............................95
  335.      15.1 Introduction ...........................................95
  336.      15.2 Example      ..........................................101
  337.      15.3 Virtual functions inherited from RWCollection..........103
  338.           15.3.1    insert().....................................103
  339.           15.3.2    find() and friends...........................103
  340.           15.3.3    remove() functions...........................106
  341.           15.3.4    apply() functions............................107
  342.           15.3.5    Functions clear()............................108
  343.      15.4 Other functions shared by all RWCollections............108
  344.           15.4.1    Class conversions............................108
  345.           15.4.2    Inserting and removing other collections.....108
  346.           15.4.3    Selection....................................109
  347.      15.5 Virtual functions inherited from RWSequenceable........109
  348.      15.6 Iterators    ..........................................111
  349.      15.7 Dictionaries ..........................................112
  350.      15.8 A note on how objects are found........................114
  351.           15.8.1    Hash collections.............................114
  352.      15.9 Storage and retrieval of "Collectable" objects.........116
  353.      15.10     Designing an RWCollectable class..................120
  354.           15.10.1   Virtual functions inherited from RWCollectable120
  355.           15.10.2   An example...................................121
  356.           15.10.3   Object destruction...........................123
  357.           15.10.4   Virtual function isA().......................123
  358.           15.10.5   Virtual function compareTo().................123
  359.           15.10.6   Virtual function isEqual()...................125
  360.           15.10.7   Virtual function hash()......................126
  361.           15.10.8   Virtual function newSpecies()................127
  362.           15.10.9   Virtual functions saveGuts(RWFile&) and
  363.                     saveGuts(RWvostream&)........................127
  364.           15.10.10  Virtual functions restoreGuts(RWFile&) and
  365.                     restoreGuts(RWvistream&).....................127
  366.           15.10.11  Putting it all together......................128
  367.           15.10.12  Summary......................................131
  368.  
  369.  
  370. Rogue Wave     Tools.h++ Class Library                v
  371.  
  372.  
  373.  
  374.  
  375.  
  376.  
  377.  
  378.  
  379.  
  380.  
  381.      15.11        More on storing and retrieving RWCollectables  131
  382.           15.11.1   Reading and writing collections..............135
  383.      15.12            Architectural notes .......................135
  384. 16. Implementation Notes.........................................139
  385.           16.1      Errors.......................................139
  386.           16.1.1    Violated preconditions.......................139
  387.           16.1.2    Invalid input................................140
  388.           16.1.3    Asynchronous errors..........................141
  389.           16.1.4    Changing the default error handler...........143
  390.           16.1.5    Error numbers and messages...................143
  391.      16.2 Dynamic Link Library...................................144
  392.           16.2.1    Example......................................144
  393. 17. Examples.....................................................157
  394.      17.1 Example 1:  The RWTime and RWDate classes .............157
  395.      17.2 Example 2:  The RWString class ........................158
  396.      17.3 Example 3:  GDlist - A class for generic
  397.                       doubly-linked lists .......................158
  398.      17.4 Example 4:  RWBinaryTree - A sorted collection of
  399.                       RWCollectableStrings ......................158
  400.      17.5 Example 5:  RWHashDictionary - A dictionary of
  401.                       keys and values ...........................161
  402.      17.6 Example 6:  RWBTreeOnDisk .............................161
  403.      17.7 Example7 & 8:  Class RWFileManager.....................162
  404.  
  405.                                     Part II
  406. Class Reference..................................................165
  407.      GBitVec(size)  .............................................167
  408.      GDlist(type)      ..........................................171
  409.      GDlistIterator(type)........................................176
  410.      GQueue(type)      ..........................................179
  411.      GSlist(type)      ..........................................182
  412.      GSlistIterator(type)........................................186
  413.      GSortedVector(val)..........................................189
  414.      GStack(type)      ..........................................193
  415.      GVector(val)      ..........................................196
  416.      RWBag             ..........................................198
  417.      RWBagIterator     ..........................................202
  418.      RWBinaryTree      ..........................................204
  419.      RWBinaryTreeIterator........................................208
  420.      RWbistream        ..........................................210
  421.      RWBitVec          ..........................................215
  422.      RWbostream        ..........................................221
  423.  
  424.  
  425. Rogue Wave     Tools.h++ Class Library               vi
  426.  
  427.  
  428.  
  429.  
  430.  
  431.  
  432.  
  433.  
  434.  
  435.  
  436.      RWBTree           ..........................................225
  437.      RWBTreeDictionary ..........................................229
  438.      RWBTreeOnDisk     ..........................................233
  439.      RWCacheManager    ..........................................236
  440.      RWCLIPstreambuf   ..........................................239
  441.      RWCollectable     ..........................................242
  442.      RWCollectableDate ..........................................246
  443.      RWCollectableInt  ..........................................248
  444.      RWCollectableString.........................................251
  445.      RWCollectableTime ..........................................253
  446.      RWCollection      ..........................................255
  447.      RWDate            ..........................................260
  448.      RWDDEstreambuf    ..........................................267
  449.      RWDlistCollectables.........................................273
  450.      RWDlistCollectablesIterator.................................278
  451.      RWErrObject       ..........................................281
  452.      RWFactory         ..........................................284
  453.      RWFile            ..........................................286
  454.      RWFileManager     ..........................................290
  455.      RWHashDictionary  ..........................................292
  456.      RWHashDictionaryIterator....................................296
  457.      RWIdentityDictionary........................................298
  458.      RWIdentitySet     ..........................................299
  459.      RWInteger         ..........................................300
  460.      RWIterator        ..........................................302
  461.      RWOrdered         ..........................................303
  462.      RWOrderedIterator ..........................................307
  463.      RWpistream        ..........................................308
  464.      RWpostream        ..........................................314
  465.      RWRegexp          ..........................................319
  466.      RWSequenceable    ..........................................323
  467.      RWSet             ..........................................325
  468.      RWSetIterator     ..........................................329
  469.      RWSlistCollectables.........................................331
  470.      RWSlistCollectablesIterator.................................336
  471.      RWSlistCollectablesQueue....................................339
  472.      RWSlistCollectablesStack....................................342
  473.      RWSortedVector    ..........................................345
  474.      RWString          ..........................................350
  475.      RWSubString       ..........................................359
  476.      RWTime            ..........................................363
  477.      RWTokenizer       ..........................................368
  478.  
  479.  
  480. Rogue Wave     Tools.h++ Class Library              vii
  481.  
  482.  
  483.  
  484.  
  485.  
  486.  
  487.  
  488.  
  489.  
  490.  
  491.      RWvistream        ..........................................370
  492.      RWvostream        ..........................................374
  493. Appendix A:  Summary of typedefs and macros......................379
  494. Appendix B:  Bibliography........................................381
  495.  
  496.  
  497.  
  498.  
  499.  
  500.  
  501.  
  502.  
  503.  
  504.  
  505.  
  506.  
  507.  
  508.  
  509.  
  510.  
  511.  
  512.  
  513.  
  514.  
  515.  
  516.  
  517.  
  518.  
  519.  
  520.  
  521.  
  522.  
  523.  
  524.  
  525.  
  526.  
  527.  
  528.  
  529.  
  530.  
  531.  
  532.  
  533.  
  534.  
  535. Rogue Wave     Tools.h++ Class Library             viii
  536.  
  537.  
  538.  
  539.  
  540.  
  541.  
  542.  
  543.  
  544.  
  545.  
  546.  
  547.  
  548.  
  549.  
  550.  
  551.                                                             S e c t i o n    1 
  552.  
  553.  
  554.                                                                    Introduction
  555.  
  556.  
  557.  
  558.  
  559. 1.1  Overview and features
  560.  
  561.  
  562.  
  563.           The Rogue Wave Tools.h++ Class Library is a set of C++ classes that
  564.           can greatly simplify your programming while maintaining the
  565.           efficiency for which C is famous.  The package includes:
  566.  
  567.  
  568.           l  Smalltalk -like collection classes:
  569.              A complete library of collection classes, modeled after the
  570.              Smalltalk-80 programming environment:  Set, Bag,
  571.              OrderedCollection, SortedCollection, Dictionary, Stack, Queue,
  572.              etc.  All of these classes can be saved to disk and restored in a
  573.              new address space, even on a different operating system!  An
  574.              object need only inherit the abstract base class RWCollectable to
  575.              have full access to all of the functionality of the collection
  576.              classes.  The interface to the Smalltalk names is done as
  577.              typedefs, allowing the actual implementation of, say, a
  578.              Dictionary to be changed from its default of a hash table of
  579.              associations, to, say, a B-Tree.
  580.  
  581.           l  Generic collection classes
  582.              Singly and doubly-linked lists, stacks, queues and vectors, using
  583.              <generic.h>, the current C++ approximation to parameterized
  584.              types.
  585.  
  586.           l  RWFile Class
  587.              Encapsulates standard file operations.
  588.  
  589.  
  590. Rogue Wave            Introduction  1
  591.  
  592.  
  593.  
  594.  
  595.  
  596.  
  597.  
  598.  
  599.                         USER'S GUIDE
  600.  
  601.           l  B-Tree disk retrieval
  602.              Efficient keyed access of disk records, using B-Trees.
  603.  
  604.           l  File Space Manager
  605.              Allocates, deallocates and coalesces free space within a file.
  606.  
  607.           l  String and character manipulation
  608.              Class RWString offers a full suite of operators and functions to
  609.              manipulate character strings, including concatenation,
  610.              comparison, indexing (with optional bounds checking), I/O, case
  611.              changes, stripping, and many other functions.  Class RWSubString
  612.              is available for extraction and assignment to substrings.  Class
  613.              RWRegexp implements pattern searches.  Class RWTokenizer can be
  614.              used to break strings into separate tokens.
  615.  
  616.           l  Time and date handling classes
  617.              Calculate the number of days between two dates, or the day of the
  618.              week a date represents; read and write days or times in arbitrary
  619.              formats; etc.
  620.  
  621.           l  Still more classes...
  622.              Bit vectors, virtual I/O streams, caching managers, ... a
  623.              complete toolbox!
  624.  
  625.           l  Persistent store
  626.              A powerful and sophisticated persistent store facility that
  627.              allows complex objects to be stored to disk or even exchanged
  628.              through a heterogeneous network or Windows 3.0's Dynamic Data
  629.              Exchange.  The object's morphology (e.g., multiple pointers to
  630.              the same object, or a circularly linked list) can be maintained.
  631.  
  632.           l  A complete error handling facility
  633.              Including a facility for handling exceptions, when they become
  634.              available.
  635.  
  636.           l  Microsoft Windows_ support:
  637.  
  638.              Specialized stream I/O classes for use with Windows Clipboard and
  639.              DDE
  640.              Allows the use of I/O streams, including Rogue Wave's virtual
  641.              streams, to exchange data through the Clipboard or DDE facility.
  642.  
  643.  
  644.  
  645. Rogue Wave            Introduction  2
  646.  
  647.  
  648.  
  649.  
  650.  
  651.  
  652.  
  653.  
  654.                         USER'S GUIDE
  655.  
  656.              DLL version
  657.              A Dynamic Link Library (DLL) version of Tools.h++ comes on the
  658.              standard distribution disk.  Classes and methods are dynamically
  659.              linked to your code, decreasing the size of your executable.
  660.  
  661.  
  662.  
  663.  
  664.  
  665.  
  666.  
  667.  
  668.  
  669.  
  670.  
  671.  
  672.  
  673.  
  674.  
  675.  
  676.  
  677.  
  678.  
  679.  
  680.  
  681.  
  682.  
  683.  
  684.  
  685.  
  686.  
  687.  
  688.  
  689.  
  690.  
  691.  
  692.  
  693.  
  694.  
  695.  
  696.  
  697.  
  698.  
  699.  
  700. Rogue Wave            Introduction  3
  701.  
  702.  
  703.  
  704.  
  705.  
  706.  
  707.  
  708.  
  709.                         USER'S GUIDE
  710.  
  711.  
  712. 1.2  Supported compilers
  713.  
  714.  
  715.  
  716.           The Classes can be compiled without modification by a wide variety of
  717.           C++ compilers:
  718.  
  719.           MS-DOS:   Borland Turbo C++ V1.01 or greater
  720.  
  721.                     Borland C++ V2.0 or greater
  722.  
  723.                     Zortech V2.10 or greater
  724.  
  725.                     Jensen and Partner's TopSpeed C++
  726.  
  727.                     Glockenspiel V2.0c (DOS) or greater
  728.  
  729.           UNIX:     Oregon Software V2.0 or greater
  730.  
  731.                     Other AT&T V 2.0- or V2.1-compatible compilers
  732.  
  733.           Usually all that is required to port Tools.h++ to another compiler is
  734.           to modify an appropriate makefile.
  735.  
  736.  
  737. 1.3  Philosophy
  738.  
  739.  
  740.  
  741.           The C++ language has several design goals that set it apart from most
  742.           other object-oriented languages.  The first and foremost is
  743.           efficiency: it is possible to write production quality code that is
  744.           every bit as efficient and small as code that has been written in C,
  745.           yet more maintainable.  A second is a "less is more" philosophy: no
  746.           feature has been included in the language that will make non-users of
  747.           the feature suffer.  For example, you will not find built-in
  748.           exception handling or garbage collection.  The result is a skeletal,
  749.           lean-and-mean language (at least as far as object-oriented languages
  750.           go) that compiles fast and results in small, efficient, but not
  751.           terribly general, code.
  752.  
  753.  
  754.  
  755. Rogue Wave            Introduction  4
  756.  
  757.  
  758.  
  759.  
  760.  
  761.  
  762.  
  763.  
  764.                         USER'S GUIDE
  765.  
  766.           Towards getting the best out of the language, the Rogue Wave
  767.           Tools.h++ class library has adopted similar goals: Efficiency,
  768.           simplicity, compactness, and predictability.
  769.  
  770.           Efficiency.  In general, you will find no feature that will slow
  771.           things down for the non-user of the feature.  As many decisions as
  772.           possible are made at compile time, consistent with the C++ philosophy
  773.           of static type checking.  In most cases, we offer a choice between
  774.           classes with extreme simplicity, but little generality, and classes
  775.           that are a little more complex, but more general.  We have chosen not
  776.           to require that all classes inherit a secular base class (such as the
  777.           class Object used by Smalltalk and The NIH Classes).  Instead, only
  778.           objects that are to be collected using the Smalltalk-like collection
  779.           classes need inherit a base class RWCollectable.  The advantage of
  780.           this is that virtual base classes are not necessary, simplifying the
  781.           inheritance tree and the difficult problem of casting from a base
  782.           class back to its derived class.
  783.  
  784.           Simplicity.  There is a temptation to keep adding subclasses to add
  785.           power or convenience for the user or to demonstrate one's prowess
  786.           with the language.  We have avoided this.  Although the overall
  787.           architecture is sophisticated and integrated, each class usually
  788.           plays just one well-defined, pivotal role.  Most functions are
  789.           extraordinarily simple: a few lines of code.
  790.  
  791.           Compactness.  An important goal was to make sure that programs
  792.           compiled small.  This was to insure that they can be used in embedded
  793.           systems or under MS-DOS.
  794.  
  795.           Predictability.  Many new users of C++ become so giddy with the power
  796.           of being able to overload esoteric operators like "&=" that they
  797.           forget about tried-and-true function calls and start redefining
  798.           everything in sight.  Again, we have avoided this and have tried hard
  799.           to make all of the familiar operators work just as you might expect -
  800.           - there are no surprises.  This approach gives great symmetry to the
  801.           class library, making it possible to do such things as, say, change
  802.           the implementation of a Dictionary from a hash table to a B-Tree with
  803.           impunity.
  804.  
  805.           In general, whenever we considered a new feature, we tried to think
  806.           as Stroustrup would: if there was already a way to do it, we left it
  807.           out!
  808.  
  809.  
  810. Rogue Wave            Introduction  5
  811.  
  812.  
  813.  
  814.  
  815.  
  816.  
  817.  
  818.  
  819.                         USER'S GUIDE
  820.  
  821.  
  822. 1.4  Conventions
  823.  
  824.  
  825.  
  826.           All Rogue Wave class names (except generic classes) start with the
  827.           letters "RW".  All function names start with a lower case letter, but
  828.           subsequent words are capitalized.  There are no underline characters
  829.           used in names.  An example of a class name is RWHashDictionary, of a
  830.           function compareTo().  Generally, abbreviations are not used in
  831.           function names, making them easy to remember.
  832.  
  833.           Some of the class names may seem unnecessarily tedious (for example,
  834.           a singly-linked list of collectables, accessible as a stack, is a
  835.           RWSlistCollectablesStack).  There are two reasons for this.  First,
  836.           using generic names like "Stack" invites a name collision with
  837.           someone else's stack class, should you write a large program that
  838.           combines many class libraries.  We have tried very hard to avoid
  839.           polluting the global name space with generic names like "String",
  840.           "Vector", "Stack", etc.  It is also for this reason (and not
  841.           megalomania!) that class names and many of the potentially generic
  842.           names have an "RW" prepended (e.g., "RWBoolean").  We have worked
  843.           hard to make sure that Tools.h++ is compatible with other class
  844.           libraries.  Secondly, the names are intended to convey as precisely
  845.           as possible what the class does.
  846.  
  847.           Nevertheless, there are a set of typedefs that give these various
  848.           classes generic names like Stack or OrderedCollection that are
  849.           consistent with the Smalltalk-80 names.  These typedefs can easily be
  850.           changed if there is a problem with duplicate names.
  851.  
  852.  
  853. 1.5  Reading this manual
  854.  
  855.  
  856.  
  857.           This manual is intended to serve two purposes: to be an introduction
  858.           to using the Rogue Wave Tools.h++ Class Library and to be an
  859.           intermediate-level tutorial on the language C++, using the Class
  860.           Library as an aid to discussing some of the more subtle aspects of
  861.           C++.  It assumes that you are familiar with the basics of C++, but
  862.           not yet an expert.  The discussion is generally more detailed than
  863.  
  864.  
  865. Rogue Wave            Introduction  6
  866.  
  867.  
  868.  
  869.  
  870.  
  871.  
  872.  
  873.  
  874.                         USER'S GUIDE
  875.  
  876.           what is necessary to actually use the library -- if you find yourself
  877.           getting overwhelmed by details, by all means, abandon the coming
  878.           sections and rely on the many examples of Section 15.
  879.  
  880.           If you are not familiar with C++ at all, we do not recommend trying
  881.           to learn it from the three definitive reference books available:
  882.           Stroustrup (1986), Lippman (1989), and Ellis and Stroustrup (1990;
  883.           sometimes ominously referred to as "The ARM" -- Annotated Reference
  884.           Manual).  Their terse (but precise) style make them better suited as
  885.           references to the language.  i.Reference books;The best introductory
  886.           books that we have seen are Weiskamp and Flamig (1990) and Eckel
  887.           (1989), although both are weak in discussing V2.X features of C++.
  888.  
  889.           In what follows, there are several references to Stroustrup and
  890.           Lippman's books -- it may be helpful to have a copy available.
  891.  
  892.           Occasionally there will be a highlighted paragraph explaining either
  893.           a key point, or "An Aside".  The latter can be ignored safely without
  894.           losing the essential thread of the discussion.
  895.  
  896.           Throughout this manual, examples, operating system commands, and code
  897.           fragments are shown in a courier font.  Class names are shown in a
  898.           Helvetica font.  Vertical ellipses are used to indicate that some
  899.           part of the code is missing:
  900.  
  901.  
  902.             main()
  903.             {
  904.             .
  905.             .    // Something happens
  906.             .
  907.             }
  908.  
  909.  
  910.  
  911.  
  912.  
  913.  
  914.  
  915.  
  916.  
  917.  
  918.  
  919.  
  920. Rogue Wave            Introduction  7
  921.  
  922.  
  923.  
  924.  
  925.  
  926.  
  927.  
  928.  
  929.  
  930.  
  931.  
  932.  
  933.  
  934.  
  935.  
  936.                                                             S e c t i o n    2 
  937.  
  938.  
  939.                                                        InstallationInstallation
  940.  
  941.  
  942.  
  943.  
  944. 2.1  Installation overview
  945.  
  946.  
  947.  
  948.           As of this writing, Tools.h++ comes on two diskettes.  This could
  949.           change.  Included in the standard distribution is:
  950.  
  951.           o  Header files;
  952.  
  953.           o  C++ source code and appropriate makefiles;
  954.  
  955.           o  A Borland Turbo C++ V1.01 precompiled library, using the large
  956.              memory model;
  957.  
  958.           o  A Borland C++ V2.0 precompiled library, using the large memory
  959.              model;
  960.  
  961.           o  A Zortech V2.18 (DOS) precompiled library, using the large memory
  962.              model;
  963.  
  964.           o  A Glockenspiel V2.0c (DOS) precompiled library, using the large
  965.              memory model;
  966.  
  967.           o  A Borland C++ V2.0 precompiled Windows DLL, using the large
  968.              memory model.
  969.  
  970.           As new C++ compilers come on the market, additional precompiled
  971.           libraries may be added.
  972.  
  973.           Makefiles have been supplied for both the MS-DOS and Unix operating
  974.           systems and for all compilers.  They will automatically take care of
  975. Rogue Wave            Installation  9
  976.  
  977.  
  978.  
  979.  
  980.  
  981.  
  982.  
  983.  
  984.                         USER'S GUIDE
  985.  
  986.           a lot of the details involved in building or rebuilding the
  987.           libraries.
  988.  
  989.           All C++ source code has a suffix of .cpp for all compilers and both
  990.           operating systems.  Because not all compilers expect this suffix,
  991.           provisions have been made in the appropriate makefile to compensate.
  992.           There is no need to rename any of the files when porting between
  993.           operating systems or compilers.
  994.  
  995.  
  996.  
  997.  
  998.  
  999.  
  1000.  
  1001.  
  1002.  
  1003.  
  1004.  
  1005.  
  1006.  
  1007.  
  1008.  
  1009.  
  1010.  
  1011.  
  1012.  
  1013.  
  1014.  
  1015.  
  1016.  
  1017.  
  1018.  
  1019.  
  1020.  
  1021.  
  1022.  
  1023.  
  1024.  
  1025.  
  1026.  
  1027.  
  1028.  
  1029.  
  1030. Rogue Wave            Installation  10
  1031.  
  1032.  
  1033.  
  1034.  
  1035.  
  1036.  
  1037.  
  1038.  
  1039.                         USER'S GUIDE
  1040.  
  1041.  
  1042. 2.2  Installation: MS-DOS
  1043.  
  1044.  
  1045.  
  1046.           Put the first diskette in the appropriate floppy disk drive and type:
  1047.  
  1048.             a:install
  1049.  
  1050.           Here "a:" has been used as the floppy drive.  Substitute as
  1051.           appropriate.  Follow the instructions on the screen.
  1052.  
  1053.           You will be left with five subdirectories:
  1054.  
  1055.           c:\rogue\rw
  1056.              Header files;
  1057.  
  1058.           c:\rogue\toolsrc
  1059.              Tools.h++ source code and makefiles;
  1060.  
  1061.           c:\rogue\lib
  1062.              A directory containing the precompiled libraries and DLL;
  1063.  
  1064.           c:\rogue\toolexam
  1065.              Tools.h++ sample programs;
  1066.  
  1067.           c:\rogue\dlldemo
  1068.              Windows 3.0 demonstration program that uses the Tools.h++ DLL.
  1069.  
  1070.  
  1071.  
  1072.           Compiler           makefile name  Precompiled DOS
  1073.                                             library
  1074.  
  1075.  
  1076.           Zortech            makefile.ztc   ztll.lib
  1077.  
  1078.           Borland Turbo C++  makefile.tcc   ttll.lib
  1079.  
  1080.           Borland C++        makefile.tcc   ttll.lib
  1081.  
  1082.           Glockenspiel       makefile.glk   gtll.lib
  1083.  
  1084.  
  1085. Rogue Wave            Installation  11
  1086.  
  1087.  
  1088.  
  1089.  
  1090.  
  1091.  
  1092.  
  1093.  
  1094.                         USER'S GUIDE
  1095.  
  1096.           Oregon Software    makefile.occ   (n/a)
  1097.  
  1098.           AT&T and compatibles                             makefile.att   (n/a)
  1099.           under Unix
  1100.  
  1101.  
  1102.  
  1103.  
  1104. Table 2-1.     Compiler manufacturer and corresponding makefiles and
  1105.           precompiled libraries.  Note that the Unix compilers do not come with
  1106.           a precompiled library.
  1107.  
  1108.  
  1109.  
  1110.  
  1111.  
  1112.  
  1113.  
  1114.  
  1115.  
  1116.  
  1117.  
  1118.  
  1119.  
  1120.  
  1121.  
  1122.  
  1123.  
  1124.  
  1125.  
  1126.  
  1127.  
  1128.  
  1129.  
  1130.  
  1131.  
  1132.  
  1133.  
  1134.  
  1135.  
  1136.  
  1137.  
  1138.  
  1139.  
  1140. Rogue Wave            Installation  12
  1141.  
  1142.  
  1143.  
  1144.  
  1145.  
  1146.  
  1147.  
  1148.  
  1149.                         USER'S GUIDE
  1150.  
  1151.  
  1152. 2.2.1 Installation: Zortech
  1153.  
  1154.           One additional step must be done to install Tools.h++ for use by the
  1155.           Zortech compiler:
  1156.  
  1157.  
  1158.  
  1159.           IMPORTANT!  Before starting, make a copy of the Zortech include file
  1160.           stream.hpp and call it stream.h, and a copy of generic.hpp and call
  1161.           it generic.h.
  1162.  
  1163.  
  1164.           For example:
  1165.  
  1166.             cd \zortech\include
  1167.             copy stream.hpp  stream.h
  1168.             copy generic.hpp generic.h
  1169.  
  1170.           We have chosen to follow the lead set by Bjarne Stroustrup in his
  1171.           definitive reference manual (and followed by other compiler
  1172.           manufacturers) in calling the streams file "stream.h" and the generic
  1173.           header file "generic.h".  Users of Zortech should be aware that
  1174.           Zortech is non-standard in this regard.
  1175.  
  1176.  
  1177. 2.2.2 Installation: Glockenspiel
  1178.  
  1179.           Under MS-DOS, Tools.h++ will only work with V2.0c or greater of the
  1180.           Glockenspiel compiler, using Microsoft C 6.0 as the backend C
  1181.           compiler.
  1182.  
  1183.           To install the Tools.h++ Class Library  for use with the Glockenspiel
  1184.           compiler, there are a few additional steps that you must take:
  1185.  
  1186.           1. You must make versions of all your include files with suffixes of
  1187.              .h, instead of .hpp.  For example:
  1188.  
  1189.                  cd \cxx20\include
  1190.                  copy generic.h++ generic.h
  1191.                  copy iostream.h++ iostream.h
  1192.                  etc.
  1193.  
  1194.              There is no "official" standard for the suffix of a C++ header
  1195. Rogue Wave            Installation  13
  1196.  
  1197.  
  1198.  
  1199.  
  1200.  
  1201.  
  1202.  
  1203.  
  1204.                         USER'S GUIDE
  1205.  
  1206.              file.  But, AT&T uses .h and it's their compiler.  Most other
  1207.              manufacturers have followed suit.  You will increase your
  1208.              portability by doing this step.
  1209.  
  1210.           2. You must uncomment the following line in <compiler.h>:
  1211.  
  1212.              /* #define __MSDOS__ 1 */  /* For MS-DOS */
  1213.  
  1214.           3. As per the Glockenspiel installation instructions, you must
  1215.              change the member "class" (a reserved keyword in C++) of the
  1216.              structure DOSERROR in <DOS.H> to something else.  They suggest
  1217.              changing it to err_class.
  1218.  
  1219.           4. Make sure you also read the directions in Section 3.2.1.4
  1220.              "Compiling a program: Glockenspiel"
  1221.  
  1222.  
  1223. 2.3  Recompiling the library: MS-DOS
  1224.  
  1225.  
  1226.  
  1227.           If you wish to use a memory model other than large, or if you are
  1228.           using a compiler / version combination other than those for which a
  1229.           precompiled library is available, you will have to recompile the
  1230.           library.  This is an easy chore that takes about 10 minutes on a
  1231.           modest 386, about 30 minutes on a 286.  Start by using an appropriate
  1232.           makefile for you compiler, listed in Table 2-1.  Specific
  1233.           instructions are given below.
  1234.  
  1235.           The resulting library name is coded as follows:
  1236.  
  1237.                ctlmwg.lib where:
  1238.  
  1239.           c  Codes the compiler manufacturer: (t) Borland; (g) Glockenspiel;
  1240.              (z) Zortech.
  1241.  
  1242.           m  Codes the memory model: (s) small; (c) compact; (m) medium; (l)
  1243.              large.
  1244.  
  1245.           w  Codes whether it is a windows library: (absent) regular DOS
  1246.              library; (w) Windows auxilary library; (d) Windows DLL import
  1247.              library.
  1248.  
  1249.           g  Codes whether it is a "debug" version of the library: (absent)
  1250. Rogue Wave            Installation  14
  1251.  
  1252.  
  1253.  
  1254.  
  1255.  
  1256.  
  1257.  
  1258.  
  1259.                         USER'S GUIDE
  1260.  
  1261.              regular version; (g) debug.
  1262.  
  1263.  
  1264. 2.3.1 Borland Turbo C++ and Borland C++
  1265.  
  1266.           The classes come with precompiled Turbo C++ and Borland C++
  1267.           libraries.  Both use the large memory model.  Should you wish to
  1268.           switch compilers or recompile using different compiler options, you
  1269.           will have to recompile.  Note that binaries created with Turbo C++
  1270.           are almost, but (unfortunately) not quite, upwardly compatible with
  1271.           Borland C++.  The difference is that a few member functions in the
  1272.           iostream facility were not inlined in Turbo C++ but were inlined in
  1273.           Borland C++, resulting in linker undefined reference errors when
  1274.           using the latter.
  1275.  
  1276.           Here's how to recompile Tools.h++, using the Borland compilers:
  1277.  
  1278.           1. Be sure to use the Borland make command.  In particular, the
  1279.              Microsoft make will not work.
  1280.  
  1281.           2. If you are changing the memory model or switching between Turbo
  1282.              C++ and Borland C++, any old object modules should be removed.
  1283.              The makefile has an entry for this:
  1284.  
  1285.              make -fmakefile.tcc clean
  1286.  
  1287.           3. Note that both the Turbo C++ and Borland C++ use the same
  1288.              makefile: makefile.tcc.  Find the makefile macro CPP in this file
  1289.              and change it to reflect the compiler you wish to use.  For
  1290.              example, to use Turbo C++, select:
  1291.  
  1292.              CPP=   tcc
  1293.  
  1294.              To use Borland C++, select:
  1295.  
  1296.              CPP=   bcc
  1297.  
  1298.           4. Check makefile.tcc for the memory model you want.  For example,
  1299.              if you wanted to compile with the medium memory model (large
  1300.              code, small data), the appropriate macro definition would be:
  1301.  
  1302.              MEMMODEL=   m
  1303.  
  1304.           5. Type:
  1305. Rogue Wave            Installation  15
  1306.  
  1307.  
  1308.  
  1309.  
  1310.  
  1311.  
  1312.  
  1313.  
  1314.                         USER'S GUIDE
  1315.  
  1316.              make -fmakefile.tcc
  1317.  
  1318.           The result would be a library named ttlm.lib in the lib subdirectory.
  1319.  
  1320.  
  1321. 2.3.2 Zortech
  1322.  
  1323.           The classes come with a precompiled library called ztll.lib that uses
  1324.           the Zortech large memory model.  Should you wish to recompile using
  1325.           different compiler options or to make a change in the classes, you
  1326.           will have to recompile.
  1327.  
  1328.           Here's how:
  1329.  
  1330.           1. Be sure to have read the directions in Section 2.2.1,
  1331.              Installation: Zortech.
  1332.  
  1333.           2. Be sure to use the Zortech make command.  In particular, the
  1334.              Microsoft make will not work.
  1335.  
  1336.           3. If you are changing the memory model any old object modules
  1337.              should be removed.  The makefile has an entry for this:
  1338.  
  1339.              make -f makefile.ztc clean
  1340.  
  1341.           4. Check the top of makefile.ztc for the memory model that you want.
  1342.              For example, if you wanted to recompile with the medium memory
  1343.              model (large code, small data), the appropriate macro definitions
  1344.              would be:
  1345.  
  1346.              MEMMODEL=   m
  1347.  
  1348.  
  1349.  
  1350.  
  1351.  
  1352.  
  1353.  
  1354.  
  1355.  
  1356.  
  1357.  
  1358.  
  1359.  
  1360. Rogue Wave            Installation  16
  1361.  
  1362.  
  1363.  
  1364.  
  1365.  
  1366.  
  1367.  
  1368.  
  1369.                         USER'S GUIDE
  1370.  
  1371.           5. Type:
  1372.  
  1373.              make -f makefile.ztc
  1374.  
  1375.           The result would be a library named ztlm.lib in the lib subdirectory.
  1376.  
  1377.  
  1378. 2.3.3 Glockenspiel
  1379.  
  1380.           The classes come with a precompiled Glockenspiel library called
  1381.           gtll.lib that uses the Glockenspiel large memory model.  Should you
  1382.           wish to recompile using different compiler options or to make a
  1383.           change in the classes, you will have to recompile.
  1384.  
  1385.           Here's how:
  1386.  
  1387.           1. Be sure to have read the directions in Section 2.2.2,
  1388.              Installation: Glockenspiel.
  1389.  
  1390.           2. Be sure to use the Microsoft nmk command.
  1391.  
  1392.           3. If you are changing the memory model, any old object modules
  1393.              should be removed.  The makefile has an entry for this:
  1394.  
  1395.              nmk -f makefile.glk clean
  1396.  
  1397.           4. Check the top of makefile.glk for the memory model that you want.
  1398.              For example, if you wanted to recompile with the medium memory
  1399.              model (large code, small data), the appropriate macro definitions
  1400.              would be:
  1401.  
  1402.              MEMMODEL=   m
  1403.  
  1404.           5. Type:
  1405.  
  1406.              nmk -f makefile.glk
  1407.  
  1408.           The result would be a library named gtlm.lib in the lib subdirectory.
  1409.  
  1410.  
  1411. 2.4  Recompiling and installation: Unix
  1412.  
  1413.  
  1414.  
  1415. Rogue Wave            Installation  17
  1416.  
  1417.  
  1418.  
  1419.  
  1420.  
  1421.  
  1422.  
  1423.  
  1424.                         USER'S GUIDE
  1425.  
  1426.           Because of the wide variety of hardware that supports Unix, it is
  1427.           impossible to provide precompiled libraries.  Instead, they must be
  1428.           built from source.
  1429.  
  1430.           If you have not specified custom formatting, you will have to first
  1431.           follow the MS-DOS installation instructions above and then transfer
  1432.           the directory contents to your Unix host.
  1433.  
  1434.           The installation procedure is done from the toolsrc subdirectory.
  1435.  
  1436.  
  1437.  
  1438.  
  1439.  
  1440.  
  1441.  
  1442.  
  1443.  
  1444.  
  1445.  
  1446.  
  1447.  
  1448.  
  1449.  
  1450.  
  1451.  
  1452.  
  1453.  
  1454.  
  1455.  
  1456.  
  1457.  
  1458.  
  1459.  
  1460.  
  1461.  
  1462.  
  1463.  
  1464.  
  1465.  
  1466.  
  1467.  
  1468.  
  1469.  
  1470. Rogue Wave            Installation  18
  1471.  
  1472.  
  1473.  
  1474.  
  1475.  
  1476.  
  1477.  
  1478.  
  1479.                         USER'S GUIDE
  1480.  
  1481.  
  1482. 2.4.1 AT&T compilers, including SCO (nee HCR), Glockenspiel, and Oasys
  1483.       compilers
  1484.  
  1485.           1. You should use the makefile "makefile.att".
  1486.  
  1487.           2. Check the tail end of makefile.att ("Conversions") to make sure
  1488.              that it is expecting the proper suffixes for your CC driver.  The
  1489.              makefile.att has been set up to assume that the driver accepts .C
  1490.              and puts out .o.  Yours may differ.  Note that you do NOT have to
  1491.              change the names of the source files.
  1492.  
  1493.           3. You will have to set your environment variables as usual.
  1494.  
  1495.  
  1496. 2.4.2 Oregon Software compiler
  1497.  
  1498.           You should use the makefile "makefile.occ".
  1499.  
  1500.  
  1501. 2.4.3 All Unix compilers
  1502.  
  1503.           1. Make sure you are in the toolsrc subdirectory and type make with
  1504.              the name of the appropriate makefile as an argument:
  1505.  
  1506.              cd toolsrc
  1507.              make -f makefile.xxx
  1508.  
  1509.           2. To make the example programs:
  1510.  
  1511.              cd ../toolexam
  1512.              make -f makefile.xxx
  1513.  
  1514.           3. Finally, to install the package, check the makefile macros
  1515.              LIBDIR, and INCLDIR to see if the default installation locations
  1516.              suit you, then from the toolsrc subdirectory type:
  1517.  
  1518.              make -f makefile.xxx  install
  1519.  
  1520.           4. The resulting library will be installed in LIBDIR and named
  1521.              librwtool.a.  The header files will be installed in INCLDIR.
  1522.  
  1523.  
  1524.  
  1525. Rogue Wave            Installation  19
  1526.  
  1527.  
  1528.  
  1529.  
  1530.  
  1531.  
  1532.  
  1533.  
  1534.                         USER'S GUIDE
  1535.  
  1536.  
  1537. 2.5  Working with the Rogue Wave Math.h++ library
  1538.  
  1539.  
  1540.  
  1541.           The Rogue Wave Tools.h++ and Math.h++ class libraries are completely
  1542.           compatible.  They use many of the same member function names and are
  1543.           designed to coexist.  Both libraries put their header files in the
  1544.           subdirectory \rogue\rw and their compiled libraries in \rogue\lib.
  1545.  
  1546.  
  1547. 2.6  Recompiling the library: Creating a debug version
  1548.  
  1549.  
  1550.  
  1551.           It is possible to create a "debug" version of the library.  See
  1552.           Section 16.1.1 for additional information.  If you do so, the name of
  1553.           the library will have a "g" appended to it.  For example, a large
  1554.           model library using the Borland C++ compiler and with debugging
  1555.           options on, would be called "ttllg.lib".
  1556.  
  1557.  
  1558.  
  1559.  
  1560.  
  1561.  
  1562.  
  1563.  
  1564.  
  1565.  
  1566.  
  1567.  
  1568.  
  1569.  
  1570.  
  1571.  
  1572.  
  1573.  
  1574.  
  1575.  
  1576.  
  1577.  
  1578.  
  1579.  
  1580. Rogue Wave            Installation  20
  1581.  
  1582.  
  1583.  
  1584.  
  1585.  
  1586.  
  1587.  
  1588.  
  1589.  
  1590.  
  1591.  
  1592.  
  1593.  
  1594.  
  1595.  
  1596.                                                             S e c t i o n    3 
  1597.  
  1598.  
  1599.                                                              Compiling Programs
  1600.  
  1601.  
  1602.  
  1603.           This section will tell you how to compile a program using the Rogue
  1604.           Wave Tools.h++ Class Library.Compiling a program
  1605.  
  1606.  
  1607. 3.1  Header files
  1608.  
  1609.  
  1610.  
  1611.           All of the Rogue Wave header files have lower-case names for ease of
  1612.           porting between MS-DOS and UNIX.  See Table 3-1 for a list of all of
  1613.           the classes, their type, and which header file must be included to
  1614.           use them.
  1615.  
  1616.  
  1617.  
  1618.  
  1619.  
  1620.     Generic class         Description                      Header file
  1621.  
  1622.  
  1623.     GBitVec(size)         Bit vector of length size        <gbitvec.h>
  1624.  
  1625.     GDlist(type)          Doubly-linked list               <gdlist.h>
  1626.  
  1627.     GDlistIterator(type)  Iterator for doubly-linked lists <gdlist.h>
  1628.  
  1629.     GSlist(type)          Singly-linked list               <gslist.h>
  1630.  
  1631.     GSlistIterator(type)  Iterator for singly-linked lists <gslist.h>
  1632.  
  1633.     GSortedVector(val)    Sorted vector                    <gsortvec.h>
  1634.  
  1635. Rogue Wave         Compiling Programs  21
  1636.  
  1637.  
  1638.  
  1639.  
  1640.  
  1641.  
  1642.  
  1643.  
  1644.                         USER'S GUIDE
  1645.  
  1646.     GStack(type)          Stack (Last In - First Out)      <gstack.h>
  1647.  
  1648.     GQueue(type)          Queue (First In - First Out)     <gqueue.h>
  1649.  
  1650.     GVector(val)          Vector of types                  <gvector.h>
  1651.  
  1652.  
  1653.  
  1654.  
  1655. Table 3-1a.    Generic collection classes and the header files that must be
  1656.           included to use them.  The actual type of the objects to be collected
  1657.           is given by the macro argument "type" or "val", except for the class
  1658.           GBitVec, where the argument is the length of the bit vector.  See
  1659.           Section14.
  1660.  
  1661.  
  1662.  
  1663.  
  1664.    Class Name                                                Header file
  1665.                                    Smalltalk typedef
  1666.  
  1667.  
  1668.    RWBag                           Bag                       <rwbag.h>
  1669.  
  1670.    RWBagIterator                   BagIterator               <rwbag.h>
  1671.  
  1672.    RWBinaryTree                    SortedCollection          <bintree.h>
  1673.  
  1674.    RWBinaryTreeIterator            SortedCollectionIterator  <bintree.h>
  1675.  
  1676.    RWBTree                                                   <btree.h>
  1677.  
  1678.    RWBTreeDictionary                                         <btrdict.h>
  1679.  
  1680.    RWCollection                    Collection                <colclass.h>
  1681.  
  1682.    RWDlistCollectables                                       <dlistcol.h>
  1683.  
  1684.    RWDlistCollectablesIterator                               <dlistcol.h>
  1685.  
  1686.    RWHashDictionary                Dictionary                <hashdict.h>
  1687.  
  1688.    RWHashDictionaryIterator        DictionaryIterator        <hashdict.h>
  1689.  
  1690. Rogue Wave         Compiling Programs  22
  1691.  
  1692.  
  1693.  
  1694.  
  1695.  
  1696.  
  1697.  
  1698.  
  1699.                         USER'S GUIDE
  1700.  
  1701.    RWIdentityDictionary            IdentityDictionary        <idendict.h>
  1702.  
  1703.    RWIdentitySet                   IdentitySet               <idenset.h>
  1704.  
  1705.    RWOrdered                       OrderedCollection         <ordcltn.h>
  1706.  
  1707.    RWOrderedIterator               OrderedCollectionIterator <ordcltn.h>
  1708.  
  1709.    RWSequenceable                  SequenceableCollection    <seqcltn.h>
  1710.  
  1711.    RWSet                           Set                       <rwset.h>
  1712.  
  1713.    RWSetIterator                   SetIterator               <rwset.h>
  1714.  
  1715.    RWSlistCollectables             LinkedList                <slistcol.h>
  1716.  
  1717.    RWSlistCollectablesIterator     LinkedListIterator        <slistcol.h>
  1718.  
  1719.    RWSlistCollectablesQueue        Queue                     <queuecol.h>
  1720.  
  1721.    RWSlistCollectablesStack        Stack                     <stackcol.h>
  1722.  
  1723.    RWSortedVector                                            <sortvec.h>
  1724.  
  1725.  
  1726.  
  1727.  
  1728.  
  1729.  
  1730.  
  1731. Table 3-1b.    The Tools.h++ "Smalltalk-like" Collection classes, their
  1732.           Smalltalk typedef (if any), and the header files that must be
  1733.           included to use them.  All objects to be collected using these
  1734.           classes must inherit the abstract base class RWCollectable.  See
  1735.           Section 15.
  1736.  
  1737.  
  1738.  
  1739.  
  1740.  
  1741.  
  1742.  
  1743.  
  1744.  
  1745. Rogue Wave         Compiling Programs  23
  1746.  
  1747.  
  1748.  
  1749.  
  1750.  
  1751.  
  1752.  
  1753.  
  1754.                         USER'S GUIDE
  1755.  
  1756.  
  1757.  
  1758.  
  1759.  
  1760.    Class Name                                                Header file
  1761.                                    Smalltalk typedef
  1762.  
  1763.  
  1764.    RWbistream                                                <bstream.h>
  1765.  
  1766.    RWBitVec                        BitVec                    <bitvec.h>
  1767.  
  1768.    RWbostream                                                <bstream.h>
  1769.  
  1770.    RWBTreeOnDisk                                             <disktree.h>
  1771.  
  1772.    RWCacheManager                                            <cacheman.h>
  1773.  
  1774.    RWCLIPstreambuf                                           <winstrea.h>
  1775.  
  1776.    RWCollectable                   Object                    <collect.h>
  1777.  
  1778.    RWCollectableAssociation                                  <collass.h>
  1779.  
  1780.    RWCollectableDate               Date                      <colldate.h>
  1781.  
  1782.    RWCollectableInt                Integer                   <collint.h>
  1783.  
  1784.    RWCollectableString             String                    <collstr.h>
  1785.  
  1786.    RWCollectableTime               Time                      <colltime.h>
  1787.  
  1788.    RWDate                                                    <rwdate.h>
  1789.  
  1790.    RWDDEstreambuf                                            <winstrea.h>
  1791.  
  1792.    RWFactory                                                 <factory.h>
  1793.  
  1794.    RWFile                                                    <rwfile.h>
  1795.  
  1796.    RWFileManager                                             <filemgr.h>
  1797.  
  1798.    RWInteger                                                 <rwint.h>
  1799.  
  1800. Rogue Wave         Compiling Programs  24
  1801.  
  1802.  
  1803.  
  1804.  
  1805.  
  1806.  
  1807.  
  1808.  
  1809.                         USER'S GUIDE
  1810.  
  1811.    RWpistream                                                <pstream.h>
  1812.  
  1813.    RWpostream                                                <pstream.h>
  1814.  
  1815.    RWRegexp                                                  <regexp.h>
  1816.  
  1817.    RWString                                                  <rwstring.h>
  1818.  
  1819.    RWTime                                                    <rwtime.h>
  1820.  
  1821.    RWTokenizer                                               <token.h>
  1822.  
  1823.    RWvistream                                                <vstream.h>
  1824.  
  1825.    RWvostream                                                <vstream.h>
  1826.  
  1827.  
  1828.  
  1829.  
  1830. Table 3-1c.    Other classes, Smalltalk typedef (if any), and the header files
  1831.           that must be included to use them.
  1832.  
  1833. 3.2  Compiling a program
  1834.  
  1835.  
  1836.  
  1837.           Consider the following simple program called "test":
  1838.  
  1839.             #include <rwdate.h>
  1840.             #include <rstream.h>
  1841.             main()
  1842.             {
  1843.                  // Construct a date with today's date:
  1844.                  RWDate date;
  1845.  
  1846.                  // Print it out:
  1847.                  cout << date;
  1848.             }
  1849.  
  1850.           If this were a C program it would probably be given a suffix of .c.
  1851.           Unfortunately, there is no standard suffix for C++ programs:  Zortech
  1852.           uses .cxx and .cpp; Turbo C++ uses .cpp; GNU uses .cc; Glockenspiel
  1853.           uses .cxx; while the AT&T compilers use .C (which is
  1854.           indistinguishable from .c under MS-DOS or VMS!).  We have adopted
  1855. Rogue Wave         Compiling Programs  25
  1856.  
  1857.  
  1858.  
  1859.  
  1860.  
  1861.  
  1862.  
  1863.  
  1864.                         USER'S GUIDE
  1865.  
  1866.           .cpp.  Fortunately, most compilers can be forced to accept a
  1867.           different suffix.
  1868.  
  1869.  
  1870. 3.2.1 Compiling a program: DOS
  1871.  
  1872.  
  1873.           3.2.1.1   Compiling a program: Borland
  1874.  
  1875.           These instructions assume that the Borland include files and
  1876.           libraries are in the locations specified by the file TURBOC.CFG.  If
  1877.           they are not, you will have to specify -I and -L flags as well, or
  1878.           change your configuration file (see the Borland User's Guide for
  1879.           instructions).
  1880.  
  1881.           If the file was named, say, test.cpp, then it could be compiled as
  1882.           follows:
  1883.  
  1884.             tcc -I\rogue\rw -ml test.cpp \rogue\lib\ttll.lib
  1885.  
  1886.           if you were using the Turbo C++ compiler and
  1887.  
  1888.             bcc -I\rogue\rw -ml test.cpp \rogue\lib\ttll.lib
  1889.  
  1890.           if you were using the Borland C++ compiler (substitute bccx for bcc
  1891.           to use the protected mode version of this compiler).
  1892.  
  1893.           These commands will compile and link in one step.  The `-I' option
  1894.           tells the compiler where to find the Rogue Wave header files; the `-
  1895.           ml' option specifies the large memory model (the model used by the
  1896.           supplied precompiled library); the \rogue\lib\ttll.lib is the full
  1897.           pathname of the precompiled Borland library using the large memory
  1898.           model.
  1899.  
  1900.           Other useful Borland options are -f87 (inline 80x87 floating point
  1901.           instructions) and -Qx (use extended memory).
  1902.  
  1903.  
  1904.           3.2.1.2   Using the Tools.h++ DLL with Borland C++
  1905.  
  1906.           The distribution disk includes a prebuilt DLL using the Borland C++
  1907.           large memory model.  Using it involves several files:
  1908.  
  1909.  
  1910. Rogue Wave         Compiling Programs  26
  1911.  
  1912.  
  1913.  
  1914.  
  1915.  
  1916.  
  1917.  
  1918.  
  1919.                         USER'S GUIDE
  1920.  
  1921.  
  1922.  
  1923.               File       Contents
  1924.  
  1925.  
  1926.               ttlld.dll  The DLL
  1927.  
  1928.               ttlld.lib  The DLL import library
  1929.  
  1930.               ttllw.lib  The DLL "auxilary" library
  1931.  
  1932.  
  1933.  
  1934.  
  1935.           To use the DLL you must link with the import library and the auxilary
  1936.           library.  The latter is necessary because it was not possible to
  1937.           "export" all classes from the DLL.  In particular, some of the
  1938.           classes (RWvistream, RWbistream, for example) inherit from iostream
  1939.           classes which Borland does not implement as "exported" classes.
  1940.           Hence, they must be statically bound into your program.
  1941.  
  1942.           Finally, to run your program, make sure that ttlld.dll is in your
  1943.           path.  Be sure to see Section 16.2 (Dynamic Link Library) for
  1944.           additional tips on using the DLL.
  1945.  
  1946.  
  1947.           3.2.1.3   Compiling a program: Zortech
  1948.  
  1949.           Before starting, be sure that the Zortech environmental variables
  1950.           INCLUDE and LIB are set to the proper search path for system
  1951.           #include's and libraries, respectively.
  1952.  
  1953.           If the file was named, say, test.cpp, then it could be compiled as
  1954.           follows:
  1955.  
  1956.             ztc -I\rogue\rw -ml test.cpp \rogue\lib\ztll.lib
  1957.  
  1958.           This command will compile and link in one step.  The `-I' option
  1959.           tells the compiler where to find the Rogue Wave header files; the `-
  1960.           ml' option specifies the large memory model (the model used by the
  1961.           supplied precompiled library); the \rogue\lib\ztll.lib is the full
  1962.           pathname of the precompiled Zortech library using the large memory
  1963.           model (substitute as appropriate).
  1964.  
  1965. Rogue Wave         Compiling Programs  27
  1966.  
  1967.  
  1968.  
  1969.  
  1970.  
  1971.  
  1972.  
  1973.  
  1974.                         USER'S GUIDE
  1975.  
  1976.           Other useful Zortech options are -f (inline 80x87 floating point
  1977.           instructions), -r (enforce strict prototyping), and -br (run in
  1978.           protected mode).
  1979.  
  1980.  
  1981.  
  1982.  
  1983.  
  1984.  
  1985.  
  1986.  
  1987.  
  1988.  
  1989.  
  1990.  
  1991.  
  1992.  
  1993.  
  1994.  
  1995.  
  1996.  
  1997.  
  1998.  
  1999.  
  2000.  
  2001.  
  2002.  
  2003.  
  2004.  
  2005.  
  2006.  
  2007.  
  2008.  
  2009.  
  2010.  
  2011.  
  2012.  
  2013.  
  2014.  
  2015.  
  2016.  
  2017.  
  2018.  
  2019.  
  2020. Rogue Wave         Compiling Programs  28
  2021.  
  2022.  
  2023.  
  2024.  
  2025.  
  2026.  
  2027.  
  2028.  
  2029.                         USER'S GUIDE
  2030.  
  2031.  
  2032.           3.2.1.4   Compiling a program: Glockenspiel
  2033.  
  2034.           Under MS-DOS, Tools.h++ will only work with V2.0c or greater of the
  2035.           Glockenspiel compiler, using Microsoft C 6.0 as the backend C
  2036.           compiler.  A prebuilt library, using the large memory model, has been
  2037.           included.  It is called gttl.lib.
  2038.  
  2039.           To use it, there are a few things you must do first:
  2040.  
  2041.           1. Make sure you have followed the instructions under Installation
  2042.              about the Glockenspiel compiler.
  2043.  
  2044.           2. You must always compile using the preprocessor flag "-
  2045.              D__GLOCK__".
  2046.  
  2047.              For example:
  2048.  
  2049.                  ccxx -D__GLOCK__ -I\rogue\rw -c yourfile.cxx
  2050.  
  2051.           3. For most programs, you will probably have to invoke link directly
  2052.              rather than using the front end "ccxx".  This is because ccxx
  2053.              leaves out the /NOI (do not ignore case) qualifier when it
  2054.              invokes the link command.  This is a bit of a hassle because you
  2055.              must list all of the libraries explicitly.  See
  2056.              toolexam\makefile.glk for an example.
  2057.  
  2058.           4. The default stacksize (0x0800) is too small for many of the
  2059.              Tools.h++ functions which depend heavily on recursion.   You can
  2060.              specify a different size in the link command.  0x2000 is
  2061.              suggested.  Again, see toolexam\makefile.glk for an example.
  2062.  
  2063.  
  2064. 3.2.2 Compiling a program: Unix
  2065.  
  2066.  
  2067.           3.2.2.1   Compiling a program: AT&T and compatibles, such as HCR
  2068.  
  2069.           The AT&T compilers accepts a suffix of .C as the default suffix for a
  2070.           C++ program.  If the the program was named "test.C", it could be
  2071.           compiled using the AT&T Version 2.0 compiler, by using:
  2072.  
  2073.             CC -D__ATT2__ -I/usr/local/include/rw test.C -lrwtool
  2074.  
  2075. Rogue Wave         Compiling Programs  29
  2076.  
  2077.  
  2078.  
  2079.  
  2080.  
  2081.  
  2082.  
  2083.  
  2084.                         USER'S GUIDE
  2085.  
  2086.           This command will compile and link in one step.
  2087.  
  2088.           1. The -D__ATT2__ preprocessor directive is required, so that the
  2089.              Tools.h++ header files can identify that you are using the AT&T
  2090.              (or compatible) compiler.
  2091.  
  2092.           2. The -I option tells the compiler where to find the Rogue Wave
  2093.              header files.  The directory /usr/local/include/rw is the default
  2094.              installation location.  Yours might differ.
  2095.  
  2096.           3. The -lrwtool flag tells the compiler to include the library
  2097.              librwtool.a in the list of libraries to be searched for
  2098.              externals.  If the library is not in a standard library "search
  2099.              path" the -L flag may have to be used.
  2100.  
  2101.           A Bourne shell script "ccpp" has been provided that can compile a
  2102.           program with suffix .cpp.  It also defines the __ATT2__ preprocessor
  2103.           directive automatically.
  2104.  
  2105.  
  2106.  
  2107.  
  2108.  
  2109.  
  2110.  
  2111.  
  2112.  
  2113.  
  2114.  
  2115.  
  2116.  
  2117.  
  2118.  
  2119.  
  2120.  
  2121.  
  2122.  
  2123.  
  2124.  
  2125.  
  2126.  
  2127.  
  2128.  
  2129.  
  2130. Rogue Wave         Compiling Programs  30
  2131.  
  2132.  
  2133.  
  2134.  
  2135.  
  2136.  
  2137.  
  2138.  
  2139.  
  2140.  
  2141.  
  2142.  
  2143.  
  2144.  
  2145.                                                             S e c t i o n    4 
  2146.  
  2147.  
  2148.                                                            Stream I/OStream I/O
  2149.  
  2150.  
  2151.  
  2152.           Great pains have been taken to make all I/O independent of the type
  2153.           of stream class that your compiler might use.  This is necessary
  2154.           because not all compiler manufacturers have upgraded to the
  2155.           relatively newer V2.X "iostream" type streams.
  2156.  
  2157.           For this reason, it is strongly recommended that the Rogue Wave
  2158.           header file <rstream.h> be included instead of <iostream.h> or
  2159.           <stream.h>.  It will chose the appropriate header file based on the
  2160.           type of compiler being used.  The macro "NL" is also available to
  2161.           indicate a "newline".  For V2.X-type iostreams, it will be expanded
  2162.           to "endl", for V1.2-type streams, it will be expanded to "\n".
  2163.  
  2164.           Using these features will result in increased portability for your
  2165.           programs.  See the table below.
  2166.  
  2167.  
  2168.  
  2169.    Compiler                       V1.2       V2.0       rstream.h     Macro
  2170.  
  2171.                                   stream.h   iostream.h  chooses      "NL"
  2172.  
  2173.                                                                    expands as
  2174.  
  2175.  
  2176.    AT&T V2.0, and compatibles     X          X          <iostream.h>  endl
  2177.  
  2178.    such as HCR and Glockenspiel
  2179.  
  2180.    Oregon Software V2.0           X          X          <iostream.h>  endl
  2181.  
  2182.    Zortech V2.X                   X                     <stream.h>    "\n"
  2183.  
  2184.  
  2185. Rogue Wave             Stream I/O  31
  2186.  
  2187.  
  2188.  
  2189.  
  2190.  
  2191.  
  2192.  
  2193.  
  2194.                         USER'S GUIDE
  2195.  
  2196.    Borland Turbo C++ and          X          X          <iostream.h>  endl
  2197.    Borland C++
  2198.  
  2199.  
  2200.  
  2201.  
  2202. Table 4-1.     This table indicates which types of streams a compiler supports.
  2203.         V1.2 stream.h refers to the "old-style" streams, V2.0 iostream.h refers
  2204.         to the "new-style" iostreams.  The header file rstream.h is a Rogue
  2205.         Wave - supplied file that chooses an appropriate streams header file.
  2206.  
  2207.  
  2208.  
  2209.  
  2210.  
  2211.  
  2212.  
  2213.  
  2214.  
  2215.  
  2216.  
  2217.  
  2218.  
  2219.  
  2220.  
  2221.  
  2222.  
  2223.  
  2224.  
  2225.  
  2226.  
  2227.  
  2228.  
  2229.  
  2230.  
  2231.  
  2232.  
  2233.  
  2234.  
  2235.  
  2236.  
  2237.  
  2238.  
  2239.  
  2240. Rogue Wave             Stream I/O  32
  2241.  
  2242.  
  2243.  
  2244.  
  2245.  
  2246.  
  2247.  
  2248.  
  2249.  
  2250.  
  2251.  
  2252.  
  2253.  
  2254.  
  2255.  
  2256.                                                             S e c t i o n    5 
  2257.  
  2258.  
  2259.                                                                  Class Overview
  2260.  
  2261.  
  2262.  
  2263.           The Tools.h++ classes generally fall into one of three categories:
  2264.  
  2265.           o  Simple classes; many of which are discussed in sections 6 through
  2266.              12.
  2267.  
  2268.           o  Generic collection classes; discussed in section 14.
  2269.  
  2270.           o  Smalltalk_-like collection classes; discussed in section 15.
  2271.  
  2272.           "Simple classes" are designed to stand alone and can be used in
  2273.           almost any context.  Examples are the RWString, RWTime, or RWFile
  2274.           classes.  They are frequently used as base classes in multiple
  2275.           inheritance situations in order to implement some more abstract
  2276.           functionality.  For example, RWCollectableString multiply inherits
  2277.           from RWString and RWCollectable, giving it the functionality of a
  2278.           string, but the "collectability" of an RWCollectable class.  It is in
  2279.           this manner that we avoid using a "cosmic object", which would force
  2280.           you into a particular class hierarchy, whether you want it or not.
  2281.           For additional details, see Section 15.12.
  2282.  
  2283.           "Generic collection classes" are so called because they use the
  2284.           <generic.h> preprocessor macros supplied with your C++ compiler, the
  2285.           current C++ approximation to templates.  They offer the advantages of
  2286.           speed and type safe usage.  Their code size can also be quite small
  2287.           when used sparingly.  Their disadvantages are their limited
  2288.           generality and power and that, when used heavily, their code size can
  2289.           be quite large because there is almost no opportunity for code reuse.
  2290.           Because they depend heavily on the preprocessor, they can also be
  2291.           difficult to debug.
  2292.  
  2293.           The "Smalltalk_-like collection classes" are so called because they
  2294.           offer much of the functionality of their Smalltalk namesakes, such as
  2295. Rogue Wave           Class Overview  33
  2296.  
  2297.  
  2298.  
  2299.  
  2300.  
  2301.  
  2302.  
  2303.  
  2304.                         USER'S GUIDE
  2305.  
  2306.           Bag, SortedCollection, etc.  However, they are not slavish imitations
  2307.           and instead pay homage to the strengths and weaknesses of C++.  Their
  2308.           greatest advantages are their simple programming interface, powerful
  2309.           I/O abilities, and high code reuse.  Their biggest disadvantages are
  2310.           their relatively high object code size when used in only small doses
  2311.           because of an initially high overhead in code machinery and their
  2312.           relative lack of type safeness.  All objects to be used by the
  2313.           Smalltalk-like collection classes must also inherit from the abstract
  2314.           base class RWCollectable.
  2315.  
  2316.           Table 5-1 lists the class hierarchy of all of the public Tools.h++
  2317.           classes.  In addition to these classes there are some additional
  2318.           classes that are used internally by the library.
  2319.  
  2320.  
  2321. 5.1  Common member functions
  2322.  
  2323.  
  2324.  
  2325.           Whatever category a class might fall into, all classes share a number
  2326.           of member functions.
  2327.  
  2328.             void    restoreFrom(RWFile&);
  2329.             void    restoreFrom(RWvistream&);
  2330.             void    saveOn(RWFile&) const;
  2331.             void    saveOn(RWvostream&) const;
  2332.  
  2333.           These functions are used to store an object to and from an RWFile and
  2334.           to and from the Rogue Wave virtual streams facility.
  2335.  
  2336.           Class RWFile encapsulates ANSI-C file I/O and is discussed in detail
  2337.           in Section 10 as well as in the Class Reference.  Objects saved using
  2338.           saveOn(RWFile&) are saved using a binary format, resulting in
  2339.           efficient storage and retrieval to files.
  2340.  
  2341.           Classes RWvistream and RWvostream are abstract base classes used by
  2342.           the Rogue Wave virtual streams facility.  The final output format is
  2343.           determined by the specializing class.  For example, RWpistream and
  2344.           RWpostream are two classes that derive from RWvistream and
  2345.           RWvostream, respectively, that store and retrieve objects using a
  2346.           "portable ASCII format".  The results can be transferred between
  2347.           different operating systems.  These classes are discussed in more
  2348.           detail in Section 9, as well as in the Class Reference.
  2349.  
  2350. Rogue Wave           Class Overview  34
  2351.  
  2352.  
  2353.  
  2354.  
  2355.  
  2356.  
  2357.  
  2358.  
  2359.                         USER'S GUIDE
  2360.  
  2361.           It is up to the user to decide whether to store to RWFile's or
  2362.           virtual streams.  The former offers the advantage of speed, but
  2363.           limits portability of the results to the host machine.  The latter is
  2364.           not as fast, but there are specializing classes (RWpistream and
  2365.           RWpostream) that allow the results to be moved to any machine1.
  2366.  
  2367.             unsigned     binaryStoreSize() const;
  2368.  
  2369.           This function returns the number of bytes of secondary storage
  2370.           necessary to store the object to a binary file (using class RWFile).
  2371.           It is useful for storing the object using classes RWFileManager and
  2372.           RWBTreeOnDisk.
  2373.  
  2374.             ostream&     operator<<(ostream& ostr, const ClassName& x);
  2375.             istream&     operator>>(istream& istr, const ClassName& x);
  2376.  
  2377.           The overloaded l-shift operator (<<) will print the contents of an
  2378.           object in a human-readable form.  Conversely, the overloaded r-shift
  2379.           operator (>>) will read and parse an object from an istream, using a
  2380.           human-understandable format.  Note that this contrasts with
  2381.           restoreFrom() and saveOn() which, although they may store and restore
  2382.           to a stream, will not necessarily do so in a form that could be
  2383.           called "human-readable".
  2384.  
  2385.           Finally, most classes have comparison and equality member functions:
  2386.  
  2387.             int     compareTo(ClassName*) const;
  2388.             RWBoolean    equalTo(ClassName*) const;
  2389.  
  2390.           and their logical operator counterparts:
  2391.  
  2392.             RWBoolean    operator==(const ClassName&) const;
  2393.             RWBoolean    operator!=(const ClassName&) const;
  2394.             RWBoolean    operator<=(const ClassName&) const;
  2395.                     
  2396.  
  2397.           1    At the time of this writing, there is another important
  2398.                advantage of RWFile's over virtual streams --- not all
  2399.                compiler manufacturers have gotten the details right in
  2400.                implementing istreams and ostreams which are used to
  2401.                implement virtual streams.  Some member functions that
  2402.                are known to have problems are seekg(), seekp(), gcount()
  2403.                and, perhaps, others.
  2404.  
  2405. Rogue Wave           Class Overview  35
  2406.  
  2407.  
  2408.  
  2409.  
  2410.  
  2411.  
  2412.  
  2413.  
  2414.                         USER'S GUIDE
  2415.  
  2416.             RWBoolean    operator>=(const ClassName&) const;
  2417.             RWBoolean    operator<(const ClassName&) const;
  2418.             RWBoolean    operator>(const ClassName&) const;
  2419.  
  2420.  
  2421.  
  2422.  
  2423.  
  2424.  
  2425.  
  2426.  
  2427.  
  2428.  
  2429.  
  2430.  
  2431.  
  2432.  
  2433.  
  2434.  
  2435.  
  2436.  
  2437.  
  2438.  
  2439.  
  2440.  
  2441.  
  2442.  
  2443.  
  2444.  
  2445.  
  2446.  
  2447.  
  2448.  
  2449.  
  2450.  
  2451.  
  2452.  
  2453.  
  2454.  
  2455.  
  2456.  
  2457.  
  2458.  
  2459.  
  2460. Rogue Wave           Class Overview  36
  2461.  
  2462.  
  2463.  
  2464.  
  2465.  
  2466.  
  2467.  
  2468.  
  2469.                         USER'S GUIDE
  2470.  
  2471. GBitVec(size)
  2472. GVector(val)
  2473.   GSortedVector(val)
  2474. ios
  2475.   RWvistream
  2476.      RWbistream
  2477.      RWpistream
  2478.   RWvostream
  2479.      RWbostream
  2480.      RWpostream
  2481. RWBitVec
  2482. RWBTreeOnDisk
  2483. RWCacheManager
  2484. RWCollectable
  2485.   RWCollection
  2486.      RWBag
  2487.      RWBinaryTree
  2488.      RWBTree
  2489.        RWBTreeDictionary
  2490.      RWSequenceable
  2491.        RWDlistCollectables
  2492.        RWOrdered
  2493.           RWSortedVector
  2494.        RWSlistCollectables
  2495.           RWSlistCollectablesQueue
  2496.           RWSlistCollectablesStack
  2497.      RWSet
  2498.        RWHashDictionary
  2499.           RWIdentityDictionary
  2500.        RWIdentitySet
  2501.   RWCollectableDate
  2502.   RWCollectableInt
  2503.   RWCollectableString
  2504.   RWCollectableTime
  2505. RWDate
  2506. RWErrObject
  2507. RWFactory
  2508. RWFile
  2509.   RWFileManager
  2510. RWInteger
  2511. RWIterator
  2512.   RWBagIterator
  2513.   RWBinaryTreeIterator
  2514.   RWDlistCollectablesIterator
  2515. Rogue Wave           Class Overview  37
  2516.  
  2517.  
  2518.  
  2519.  
  2520.  
  2521.  
  2522.  
  2523.  
  2524.                         USER'S GUIDE
  2525.  
  2526.   RWSetIterator
  2527.      RWHashDictionaryIterator
  2528.   RWOrderedIterator
  2529.   RWSlistCollectablesIterator
  2530. RWMemoryPool
  2531. RWRegexp
  2532. RWSlist
  2533.   GQueue(type)
  2534.   GSlist(type)
  2535.   GStack(type)
  2536.   RWDlist
  2537.      GDlist(type)
  2538. RWSlistIterator
  2539.   GSlistIterator(type)
  2540.   RWDlistIterator
  2541.      GDlistIterator(type)
  2542. RWString
  2543. RWSubString
  2544. RWTime
  2545. RWTokenizer
  2546. streambuf
  2547.   strstreambuf
  2548.      RWCLIPstreambuf
  2549.      RWDDEstreambuf
  2550.  
  2551. Table 5-1.     The class hierarchy of the public Tools.h++ classes.  Classes
  2552.           which use multiple inheritance are shown in italics.
  2553.  
  2554.  
  2555.  
  2556.  
  2557.  
  2558.  
  2559.  
  2560.  
  2561.  
  2562.  
  2563.  
  2564.  
  2565.  
  2566.  
  2567.  
  2568.  
  2569.  
  2570. Rogue Wave           Class Overview  38
  2571.  
  2572.  
  2573.  
  2574.  
  2575.  
  2576.  
  2577.  
  2578.  
  2579.  
  2580.  
  2581.  
  2582.  
  2583.  
  2584.  
  2585.  
  2586.                                                             S e c t i o n    6 
  2587.  
  2588.  
  2589.                                                    Using Class RWStringRWString
  2590.  
  2591.  
  2592.  
  2593.           The RWString class has many powerful and convenient string processing
  2594.           features that are much more convenient than the standard C <string.h>
  2595.           functions, but just as efficient.
  2596.  
  2597.  
  2598. 6.1  Example
  2599.  
  2600.  
  2601.  
  2602.           Here is a short example that exercises the RWString class:
  2603.  
  2604.             #include <rwstring.h>
  2605.             #include <regexp.h>
  2606.             #include <rstream.h>
  2607.  
  2608.             main()
  2609.             {
  2610.               RWString a;
  2611.  
  2612.               RWRegexp re("V[0-9]\.[0-9]+");
  2613.               while( a.readLine(cin) ){
  2614.                 a(re) = "V4.0";
  2615.                 cout << a << NL;
  2616.               }
  2617.             }
  2618.  
  2619.           Program input:
  2620.  
  2621.             This text describes V1.2.  For more
  2622.             information see the file groggo.doc.
  2623.             The current version V1.2 implements...
  2624.  
  2625. Rogue Wave        Using Class RWString  39
  2626.  
  2627.  
  2628.  
  2629.  
  2630.  
  2631.  
  2632.  
  2633.  
  2634.                         USER'S GUIDE
  2635.  
  2636.           Program output:
  2637.  
  2638.             This text describes V4.0.  For more
  2639.             information see the file groggo.doc.
  2640.             The current version V4.0 implements...
  2641.  
  2642.           This example reads lines from standard input and searches them for a
  2643.           pattern matching the regular expression "V[0-9]\.[0-9]+".  This
  2644.           expression matches "version numbers" between V0 and V9: V1.2, V1.22,
  2645.           but not V12.3.  If a match is found, then the pattern is replaced
  2646.           with the string "V4.0".  The magic here is in the expression
  2647.  
  2648.             a(re) = "V4.0";
  2649.  
  2650.           The function call operator (i.e., RWString::operator()) has been
  2651.           overloaded to take an argument of type RWRegexp -- the regular
  2652.           expression.  It returns a "substring" that delimits the regular
  2653.           expression, or a null substring if the expression is not found.  The
  2654.           substring assignment operator is then called and replaces the
  2655.           delimited string with the contents of the right hand side, or does
  2656.           nothing if this is the null substring.
  2657.  
  2658.  
  2659. 6.2  Reference counting
  2660.  
  2661.  
  2662.  
  2663.           Class RWString uses reference counting to minimize copying (see, for
  2664.           example, Stroustrup, 1986, Section 6).  The great advantage to this
  2665.           approach is speed.  Referencing old data via a pointer is much faster
  2666.           than copying it.
  2667.  
  2668.  
  2669.           Both the copy constructor
  2670.  
  2671.             RWString::RWString(const RWString&);
  2672.  
  2673.           and the assignment operator
  2674.  
  2675.             RWString&  RWString::operator=(const RWString&);
  2676.  
  2677.  
  2678.  
  2679.  
  2680. Rogue Wave        Using Class RWString  40
  2681.  
  2682.  
  2683.  
  2684.  
  2685.  
  2686.  
  2687.  
  2688.  
  2689.                         USER'S GUIDE
  2690.  
  2691.  
  2692.           use reference semantics.  That is, they will merely reference the
  2693.           argument, rather than copy it.  The result is a shallow copy (see
  2694.           Section 13.1.1.2).
  2695.  
  2696.  
  2697.           If a RWString is initialized with another RWString via the copy
  2698.           constructor
  2699.  
  2700.             RWString(const RWString&);
  2701.  
  2702.           then their data will share the same memory -- if one RWString is
  2703.           changed, the other will change.  The following code fragment
  2704.           illustrates:
  2705.  
  2706.  
  2707.             RWString s1 = "this is a string";     // Construct a RWString.
  2708.             RWString s2 = s1; // Construct with shared data.
  2709.  
  2710.             cout << s1 << NL << s2 << NL;
  2711.  
  2712.             // Now change s2:
  2713.             s2(0) = 'T';
  2714.  
  2715.             cout << NL<< s1 << NL << s2 << NL;
  2716.  
  2717.           This will produce the following output:
  2718.  
  2719.             this is a string
  2720.             this is a string
  2721.  
  2722.             This is a string
  2723.             This is a string
  2724.  
  2725.           Note that the first element of both s1 and s2 changed -- they share
  2726.           the same data.
  2727.  
  2728.           This may sound confusing -- two objects sharing the same data -- but
  2729.           generally it is not a problem.  The reason is that the copy
  2730.           constructor and assignment operator are frequently called upon to
  2731.           construct an object from a temporary.  Consider an example that is
  2732.           perhaps more typical:
  2733.  
  2734.  
  2735. Rogue Wave        Using Class RWString  41
  2736.  
  2737.  
  2738.  
  2739.  
  2740.  
  2741.  
  2742.  
  2743.  
  2744.                         USER'S GUIDE
  2745.  
  2746.             RWString a1 = "Pioneering ";
  2747.             RWString a2 = "does not pay.";
  2748.  
  2749.             RWString a3 = a1 + a2;
  2750.             cout << a3 << NL;
  2751.  
  2752.           The "+" operator has been overloaded for strings to concatenate its
  2753.           two arguments together.  Hence, this will produce2:
  2754.  
  2755.             Pioneering does not pay.
  2756.  
  2757.           The results of a1 + a2 produces a temporary -- it is never given a
  2758.           name and it is destroyed "at the first opportunity".  Hence, there
  2759.           will be only one copy of its data when a3 takes on its identity.
  2760.  
  2761.           Assignment to another RWString works in a similar manner.  The
  2762.           following
  2763.  
  2764.             RWString name("Seldom seen Smith");
  2765.             RWString name2;
  2766.             name2 = name;        // name2 references name's data
  2767.             name2(7) = `S';      // Changes both name and name2
  2768.             cout << name << NL << name2 << NL;
  2769.  
  2770.           produces:
  2771.  
  2772.             Seldom Seen Smith
  2773.             Seldom Seen Smith
  2774.  
  2775.  
  2776.           Note that only the copy constructor and the assignment operator that
  2777.           take an RWString as an argument are affected.  In particular,
  2778.           construction from or assignment to a character string will copy the
  2779.           string.
  2780.  
  2781.  
  2782.           Here's an example:
  2783.  
  2784.             char dat[] = "eureka!";
  2785.             RWString a1(dat);  // Construct from character string
  2786.                     
  2787.  
  2788.           2    Andrew Carnegie.
  2789.  
  2790. Rogue Wave        Using Class RWString  42
  2791.  
  2792.  
  2793.  
  2794.  
  2795.  
  2796.  
  2797.  
  2798.  
  2799.                         USER'S GUIDE
  2800.  
  2801.             RWString a2;
  2802.             a2 = dat;          // Assign to character string
  2803.             dat[0] = `E';
  2804.  
  2805.             cout << a1 << NL << a2 << NL << dat << NL;
  2806.  
  2807.           This will produce:
  2808.  
  2809.             eureka!
  2810.             eureka!
  2811.             Eureka!
  2812.  
  2813.           What if you want to construct a RWString from another RWString, but
  2814.           don't want them to share the same data?
  2815.  
  2816.  
  2817.  
  2818.           The member function copy() will return a distinct copy of a RWString
  2819.           and can be used where it is necessary to have unique data.  That is,
  2820.           it will make a deep copy (see Section 13.1.1.2).
  2821.  
  2822.  
  2823.           Here's an example:
  2824.  
  2825.             RWString b1 = "Copy 1";
  2826.             RWString b2 = b1.copy();    // Construct b2 with its own data
  2827.  
  2828.             b2(5) = `2';      // Now changing b2 will not change b1
  2829.             cout << b1 << NL << b2 << NL;
  2830.  
  2831.           This will produce:
  2832.  
  2833.             Copy 1
  2834.             Copy 2
  2835.  
  2836. 6.3  Member functions
  2837.  
  2838.  
  2839.  
  2840.           Class RWString has member functions to read, compare, store, restore,
  2841.           concatenate, prepend, and append RWStrings and char*'s.  Operators
  2842.           allow access to individual characters, with or without bounds
  2843.           checking.  The details of the RWString class capabilities are
  2844.           summarized in Part II: Class Reference.  Example 2 in Section 17
  2845. Rogue Wave        Using Class RWString  43
  2846.  
  2847.  
  2848.  
  2849.  
  2850.  
  2851.  
  2852.  
  2853.  
  2854.                         USER'S GUIDE
  2855.  
  2856.           illustrates the use of the RWString class.  RWStrings are also used
  2857.           in various ways as keys and collectable objects in Examples 3-6.
  2858.  
  2859.  
  2860.  
  2861.  
  2862.  
  2863.  
  2864.  
  2865.  
  2866.  
  2867.  
  2868.  
  2869.  
  2870.  
  2871.  
  2872.  
  2873.  
  2874.  
  2875.  
  2876.  
  2877.  
  2878.  
  2879.  
  2880.  
  2881.  
  2882.  
  2883.  
  2884.  
  2885.  
  2886.  
  2887.  
  2888.  
  2889.  
  2890.  
  2891.  
  2892.  
  2893.  
  2894.  
  2895.  
  2896.  
  2897.  
  2898.  
  2899.  
  2900. Rogue Wave        Using Class RWString  44
  2901.  
  2902.  
  2903.  
  2904.  
  2905.  
  2906.  
  2907.  
  2908.  
  2909.                         USER'S GUIDE
  2910.  
  2911.           For example, a code fragment to read two RWStrings, concatenate them,
  2912.           convert to upper case, and output the results, is:
  2913.  
  2914.             RWString s1, s2;
  2915.             cin >> s1 >> s2;
  2916.             cout << toUpper(s1+s2);
  2917.  
  2918. 6.4  SubStrings:RWString substrings
  2919.  
  2920.  
  2921.  
  2922.           A separate RWSubString class supports substring extraction and
  2923.           modification.  There are no public constructors -- RWSubStrings are
  2924.           constructed indirectly by various member functions of RWString, and
  2925.           then destroyed at the first opportunity.  The resulting substring can
  2926.           be used in a variety of situations.
  2927.  
  2928.           For example, a RWString can be constructed from a substring:
  2929.  
  2930.             RWString s("this is a string");
  2931.             // Construct a RWString from a substring:
  2932.             RWString s2 = s(0, 4);      // "this"
  2933.  
  2934.           The result is a string s2 that contains a copy of the first four
  2935.           characters of s (it will not share memory with s).
  2936.  
  2937.           RWSubstrings may also be used as lvalues in an assignment, either to
  2938.           a character string, or to a RWString or RWSubString:
  2939.  
  2940.             // Construct a RWString:
  2941.             RWString article("the");
  2942.             RWString s("this is a string");
  2943.             s(0, 4) = "that";      // "that is a string"
  2944.             s(8, 1) = article;     // "that is the string"
  2945.  
  2946.           Note that assignment is not a conformal operation: the two sides of
  2947.           the assignment operator need not have the same number of characters.
  2948.  
  2949.  
  2950. 6.5  Pattern matching
  2951.  
  2952.  
  2953.  
  2954.           Class RWString supports string search and pattern matching using a
  2955. Rogue Wave        Using Class RWString  45
  2956.  
  2957.  
  2958.  
  2959.  
  2960.  
  2961.  
  2962.  
  2963.  
  2964.                         USER'S GUIDE
  2965.  
  2966.           Rabin-Karp hashing algorithm.  This technique uses an efficient
  2967.           method to compute a hash value for a pattern of length N and checking
  2968.           it against N-sized segments within a text of length M (>N).  The
  2969.           algorithm takes time proportional to N+M (brute force searching
  2970.           techniques take time NM).  Since the method only finds a position in
  2971.           the text which has the same hash value as the pattern, the paranoid
  2972.           will still want to do a direct comparison.  This can be done by
  2973.           calling the static member function setParanoidCheck().  However,
  2974.           because the effective hashing table is extremely large, it is very
  2975.           unlikely that two different patterns would hash to the same value.
  2976.  
  2977.           Here is an example.  The code fragment:
  2978.  
  2979.             RWString s("curiouser and curiouser.");
  2980.             int i = s.index("curious");
  2981.  
  2982.           will find the start of the first occurrence of "curious" in s.  The
  2983.           result is that i will be set to "0".  To find the index of the next
  2984.           occurrence use:
  2985.  
  2986.             i = s.index("curious", i++);
  2987.  
  2988.           which will result in i being set to "14".
  2989.  
  2990.           Pattern searches can be made either case sensitive or insensitive by
  2991.           calling the static member function setCaseSensitive() first.
  2992.  
  2993.           Note that both setParanoidCheck() and setCaseSensitive() are static
  2994.           member functions -- all instances of RWString will share the same
  2995.           settings.
  2996.  
  2997.  
  2998. 6.5.1 Regular expressions
  2999.  
  3000.           The Tools.h++ Class Library supports regular expression searches.
  3001.           See Part II: Class Reference, under RWRegexp, for details of the
  3002.           regular expression syntax.  A regular expression can be used to
  3003.           return a substring.  Here's an example that might be used to match
  3004.           all Windows messages (prefix of WM_):
  3005.  
  3006.  
  3007.  
  3008.  
  3009.  
  3010. Rogue Wave        Using Class RWString  46
  3011.  
  3012.  
  3013.  
  3014.  
  3015.  
  3016.  
  3017.  
  3018.  
  3019.                         USER'S GUIDE
  3020.  
  3021.             #include <rwstring.h>
  3022.             #include <regexp.h>
  3023.             #include <rstream.h>
  3024.  
  3025.             main()
  3026.             {
  3027.               RWString a("A message named WM_CREATE");
  3028.  
  3029.               // Construct a Reg. Expr. to match Windows messages:
  3030.               RWRegexp re("WM_[A-Z]*");
  3031.               cout << a(re) << NL;
  3032.  
  3033.           Program output:
  3034.  
  3035.             WM_CREATE
  3036.  
  3037.           The function call operator for RWString has been overloaded to take
  3038.           an argument of type RWRegexp.  It returns a RWSubString matching the
  3039.           expression, or the null substring if there is no such expression.
  3040.  
  3041.  
  3042.  
  3043.  
  3044.  
  3045.  
  3046.  
  3047.  
  3048.  
  3049.  
  3050.  
  3051.  
  3052.  
  3053.  
  3054.  
  3055.  
  3056.  
  3057.  
  3058.  
  3059.  
  3060.  
  3061.  
  3062.  
  3063.  
  3064.  
  3065. Rogue Wave        Using Class RWString  47
  3066.  
  3067.  
  3068.  
  3069.  
  3070.  
  3071.  
  3072.  
  3073.  
  3074.                         USER'S GUIDE
  3075.  
  3076.  
  3077. 6.6  Tokenizer
  3078.  
  3079.  
  3080.  
  3081.           Class RWTokenizer can be used to break a string up into tokens,
  3082.           separated by an arbitrary "white space".  See Part II: Class
  3083.           Reference, under RWTokenizer, for additional details.  Here's an
  3084.           example:
  3085.  
  3086.             #include <token.h>
  3087.             #include <rwstring.h>
  3088.             #include <rstream.h>
  3089.  
  3090.             main()
  3091.             {
  3092.  
  3093.             RWString a("a string with five tokens");
  3094.  
  3095.             RWTokenizer next(a);
  3096.  
  3097.             int i = 0;
  3098.  
  3099.               // Advance until the null string is returned:
  3100.               while( next() ) i++;
  3101.  
  3102.               cout << i << NL
  3103.  
  3104.           Program output:
  3105.  
  3106.             5
  3107.  
  3108.           This program counts the number of tokens in the string.  The function
  3109.           call operator for class RWTokenizer has been overloaded to mean
  3110.           "advance to the next token and return it as a RWSubString", much like
  3111.           any other iterator.  When there are no more tokens, it returns the
  3112.           null substring.  Because RWSubString has a type conversion to char*
  3113.           which has been defined to mean "return zero if this is the null
  3114.           substring, the start of the substring otherwise", the loop will be
  3115.           broken once the null substring is encountered.
  3116.  
  3117.  
  3118.  
  3119.  
  3120. Rogue Wave        Using Class RWString  48
  3121.  
  3122.  
  3123.  
  3124.  
  3125.  
  3126.  
  3127.  
  3128.  
  3129.  
  3130.  
  3131.  
  3132.  
  3133.  
  3134.  
  3135.  
  3136.                                                             S e c t i o n    7 
  3137.  
  3138.  
  3139.                                                        Using Class RWDateRWDate
  3140.  
  3141.  
  3142.  
  3143.           Class RWDate represents a date, stored as a Julian day number.  It is
  3144.           based on algorithms from The NIH Class Library (K.E. Gorlen, see
  3145.           Appendix B).
  3146.  
  3147.           The algorithm to convert a Gregorian calendar date (for example
  3148.           January 10, 1990) to a Julian day number is given in: Algorithm 199
  3149.           from Communications of the ACM, Volume 6, No. 8, Aug. 1963, p. 444.
  3150.  
  3151.           The Gregorian calendar was introduced by Pope Gregory XIII in 1582,
  3152.           and was adopted by England on September 14, 1752.  Class RWDate will
  3153.           not provide valid dates before 1582.
  3154.  
  3155.  
  3156. 7.1  Constructors
  3157.  
  3158.  
  3159.  
  3160.           A RWDate may be constructed in several ways.  For example:
  3161.  
  3162.           1. Construct a RWDate with the current date:
  3163.  
  3164.                  RWDate d;
  3165.  
  3166.           2. Construct a RWDate for a given day of the year (1-365) and a
  3167.              given year (e.g., 1989 or 89)
  3168.  
  3169.                  RWDate d(24, 1990);         // 1/24/1990
  3170.                  RWDate d2(24, 90);          // 1/24/1990
  3171.  
  3172.           3. Construct a RWDate for a given day of the month (1-31), month
  3173.              name (e.g., January, JAN, or Jan) or month number (1-12) and
  3174.              year:
  3175. Rogue Wave         Using Class RWDate  49
  3176.  
  3177.  
  3178.  
  3179.  
  3180.  
  3181.  
  3182.  
  3183.  
  3184.                         USER'S GUIDE
  3185.  
  3186.                  RWDate d(10, "MAR", 90);         // 3/10/1990
  3187.  
  3188.           4. Construct a RWDate from a RWTime:
  3189.  
  3190.                  RWTime t;                   // Current time.
  3191.                  RWDate d(t);
  3192.  
  3193. 7.2  Member functions
  3194.  
  3195.  
  3196.  
  3197.           There are member functions to read, compare, store, restore, add and
  3198.           subtract RWDates.  A RWDate may return (for example) the name of the
  3199.           month, whether it is a leap year, etc.  Dates can be printed with a
  3200.           variety of formats.  A complete list of member functions is included
  3201.           in Part II: Class Reference.  Example 1 (see Section 17) illustrates
  3202.           the use of this class.
  3203.  
  3204.  
  3205. 7.3  Example
  3206.  
  3207.  
  3208.  
  3209.             #include <rwdate.h>
  3210.             #include <rstream.h>
  3211.  
  3212.             main(){
  3213.               RWDate dd(6, "January", 1990);
  3214.               dd.setPrintOption(RWDate::terse);
  3215.               cout << dd<< ", a " << dd.nameOfDay() << NL;
  3216.  
  3217.               RWDate prev = dd.previous("Sunday");
  3218.  
  3219.               cout << "The previous Sunday is: " << prev << NL;
  3220.             }
  3221.  
  3222.           Program output:
  3223.  
  3224.             1-Jan-90, a Saturday
  3225.             The previous Sunday is: 31-Dec-89
  3226.  
  3227.  
  3228.  
  3229.  
  3230. Rogue Wave         Using Class RWDate  50
  3231.  
  3232.  
  3233.  
  3234.  
  3235.  
  3236.  
  3237.  
  3238.  
  3239.  
  3240.  
  3241.  
  3242.  
  3243.  
  3244.  
  3245.  
  3246.                                                             S e c t i o n    8 
  3247.  
  3248.  
  3249.                                                        Using Class RWTimeRWTime
  3250.  
  3251.  
  3252.  
  3253.           Class RWTime represents a time, stored as the number of seconds since
  3254.           1 January 1901.  It is based on algorithms from The NIH Class Library
  3255.           (K.E. Gorlen, see Appendix B).
  3256.  
  3257.           For this class to function correctly, your computer's system clock
  3258.           must be set and functioning correctly.  If you are using a PC, be
  3259.           sure the batteries that power the system clock are charged.
  3260.  
  3261.  
  3262. 8.1  Setting the time zone
  3263.  
  3264.  
  3265.  
  3266.           The UNIX operating system provides for setting the local time zone
  3267.           and for establishing whether daylight savings time is locally
  3268.           observed.  If these switches have been properly set for your system,
  3269.           class RWTime should function properly.
  3270.  
  3271.           For MS-DOS users, you will have to set these switches yourself.  How
  3272.           you do this depends on the compiler you are using.  If you do
  3273.           nothing, the class will function properly for local time, but may not
  3274.           give the proper Greenwich Mean Time (GMT) -- the computer has no
  3275.           other way of knowing the offset from local time to GMT.
  3276.  
  3277.           For Borland users, you must set your environment variable TZ to the
  3278.           appropriate time zone.  For example:
  3279.  
  3280.             set TZ=PST8PDT
  3281.  
  3282.           See the documentation for function tzset() within the Borland Library
  3283.           Reference Guide for further information.
  3284.  
  3285. Rogue Wave         Using Class RWTime  51
  3286.  
  3287.  
  3288.  
  3289.  
  3290.  
  3291.  
  3292.  
  3293.  
  3294.                         USER'S GUIDE
  3295.  
  3296.           For Zortech users, you must set the time zone manually in the file
  3297.           "rwtime.cpp".  Time zones, in hours west of GMT, are provided as an
  3298.           enumeration in "rwtime.cpp".  You must set the macro LOCAL_TIME_ZONE.
  3299.  
  3300.  
  3301.  
  3302.  
  3303.  
  3304.  
  3305.  
  3306.  
  3307.  
  3308.  
  3309.  
  3310.  
  3311.  
  3312.  
  3313.  
  3314.  
  3315.  
  3316.  
  3317.  
  3318.  
  3319.  
  3320.  
  3321.  
  3322.  
  3323.  
  3324.  
  3325.  
  3326.  
  3327.  
  3328.  
  3329.  
  3330.  
  3331.  
  3332.  
  3333.  
  3334.  
  3335.  
  3336.  
  3337.  
  3338.  
  3339.  
  3340. Rogue Wave         Using Class RWTime  52
  3341.  
  3342.  
  3343.  
  3344.  
  3345.  
  3346.  
  3347.  
  3348.  
  3349.                         USER'S GUIDE
  3350.  
  3351.           For example,
  3352.  
  3353.             LOCAL_TIME_ZONE = USEastern;
  3354.  
  3355.           sets the local time to Eastern Standard Time.  The default is Pacific
  3356.           Standard Time.  The file must be recompiled for the changes to take
  3357.           effect.
  3358.  
  3359.           For both compilers, you must also set the switch DST_OBSERVED to TRUE
  3360.           (the default) or FALSE, depending on whether or not daylight savings
  3361.           time is locally observed.  Note that this does not mean whether
  3362.           daylight savings time is currently in effect -- Class RWTime will
  3363.           determine this -- just whether it is locally observed.  The file must
  3364.           be recompiled for any changes to take effect.
  3365.  
  3366.  
  3367. 8.2  Constructors
  3368.  
  3369.  
  3370.  
  3371.           A RWTime may be constructed in several ways:
  3372.  
  3373.           1. Construct a RWTime with the local time:
  3374.  
  3375.                  RWTime t;
  3376.  
  3377.           2. Construct a RWTime with today's date, at the specified local hour
  3378.              (0-23), minute (0-59) and second (0-59):
  3379.  
  3380.                  RWTime t(16, 45, 0);        // 16:45:00
  3381.  
  3382.           3. Construct a RWTime for a given date and local time:
  3383.  
  3384.                  RWDate d(2, "June", 1952);
  3385.                  RWTime t(d, 16, 45, 0);     // 6/2/52 16:45:00
  3386.  
  3387. 8.3  Member functions
  3388.  
  3389.  
  3390.  
  3391.           Class RWTime has member functions to compare, store, restore, add and
  3392.           subtract RWTimes.  An RWTime may return hour, minute or second, local
  3393.           or GMT.  A complete list of member functions is included in Part II:
  3394.           Class Reference.  Example 1 (see Section 17.1) illustrates the use of
  3395. Rogue Wave         Using Class RWTime  53
  3396.  
  3397.  
  3398.  
  3399.  
  3400.  
  3401.  
  3402.  
  3403.  
  3404.                         USER'S GUIDE
  3405.  
  3406.           this class.
  3407.  
  3408.           For example, a code fragment to output the (local) hour and (GMT)
  3409.           hour is:
  3410.  
  3411.  
  3412.             RWTime t;
  3413.             cout << t.hour();
  3414.             cout << t.hourGMT();
  3415.  
  3416.  
  3417.  
  3418.  
  3419.  
  3420.  
  3421.  
  3422.  
  3423.  
  3424.  
  3425.  
  3426.  
  3427.  
  3428.  
  3429.  
  3430.  
  3431.  
  3432.  
  3433.  
  3434.  
  3435.  
  3436.  
  3437.  
  3438.  
  3439.  
  3440.  
  3441.  
  3442.  
  3443.  
  3444.  
  3445.  
  3446.  
  3447.  
  3448.  
  3449.  
  3450. Rogue Wave         Using Class RWTime  54
  3451.  
  3452.  
  3453.  
  3454.  
  3455.  
  3456.  
  3457.  
  3458.  
  3459.  
  3460.  
  3461.  
  3462.  
  3463.  
  3464.  
  3465.  
  3466.                                                             S e c t i o n    9 
  3467.  
  3468.  
  3469.                                                                 Virtual Streams
  3470.  
  3471.  
  3472.  
  3473.           Virtual streamsThe new "iostream" facility, featured in C++ V2.X
  3474.           compiliant compilers, has proven to be a wonderfully adaptive
  3475.           resource, thanks to its clean and complete abstraction of input and
  3476.           output through sequential "streams" of bytes whose source and
  3477.           disposition is completely transparent to the user of those streams.
  3478.           It is well worth becoming familiar with its abilities.
  3479.  
  3480.           With the Rogue Wave "virtual streams" extensions, even the formatting
  3481.           of the items inserted into the streams can be made abstract.
  3482.           Furthermore, two sets of specialized streambufs are included with the
  3483.           Tools.h++ library that allow iostreams to be used to transfer data
  3484.           through the Microsoft Windows_ Clipboard or Dynamic Data Exchange
  3485.           (DDE) facilities.  The result is that the same code that is used, for
  3486.           example, to store a complex structure to a conventional disk-based
  3487.           file can also be used to transfer that structure through the DDE
  3488.           facility to another application!
  3489.  
  3490.           A limited subset of these extensions is also available for users of
  3491.           the older C++ V1.2 style "stream" classes.
  3492.  
  3493.           Classes RWvistream and RWvostream are abstract base classes with a
  3494.           whole suite of pure virtual functions operator<<(), put(), get(), and
  3495.           the like, for all of the basic built in types and arrays of built in
  3496.           types:
  3497.  
  3498.  
  3499.  
  3500.  
  3501.  
  3502.  
  3503.  
  3504.  
  3505. Rogue Wave          Virtual Streams  55
  3506.  
  3507.  
  3508.  
  3509.  
  3510.  
  3511.  
  3512.  
  3513.  
  3514.                         USER'S GUIDE
  3515.  
  3516.             class RWvistream : public ios {
  3517.             public:
  3518.               virtual RWvistream&  operator>>(char&) = 0;
  3519.               virtual RWvistream&  operator>>(double&) = 0;
  3520.               virtual int          get() = 0;
  3521.               virtual RWvistream&  get(char&) = 0;
  3522.               virtual RWvistream&  get(double&) = 0;
  3523.               virtual RWvistream&  get(char*, unsigned N) = 0;
  3524.               virtual RWvistream&  get(double*, unsigned N) = 0;
  3525.               .
  3526.               .
  3527.               .
  3528.             };
  3529.  
  3530.             class RWvostream : public ios {
  3531.             public:
  3532.               virtual RWvostream&  operator<<(char) = 0;
  3533.               virtual RWvostream&  operator<<(double) = 0;
  3534.               virtual RWvostream&  put(char) = 0;
  3535.               virtual RWvostream&  put(double) = 0;
  3536.               virtual RWvostream&  put(const char*, unsgined N) = 0;
  3537.               virtual RWvostream&  put(const double*, unsigned N) = 0;
  3538.               .
  3539.               .
  3540.               .
  3541.             };
  3542.  
  3543.           Streams that inherit from RWvistream and RWvostream are intended to
  3544.           store builtins to specialized streams in a format that is transparent
  3545.           to the user of the classes.  Note that they inherit from the V2.X
  3546.           iostreams base class ios3, hence all of the ios functions, such as
  3547.           good(), eof(), etc., can be used on them.
  3548.  
  3549.           Because the virtual streams do not retain any information about their
  3550.           underlying ios base class (or, more importantly, its associated
  3551.           streambuf), they can be freely interchanged with regular streams --
  3552.           using them does not lock you into doing all your file I/O with them.
  3553.                     
  3554.  
  3555.           3    Compilers that implement V2.X type iostreams only.  When
  3556.                RWvistream and RWvostream are used with compilers that
  3557.                use V1.2 type streams, a different inheritance structure
  3558.                is used.  See Part II: Class Reference.
  3559.  
  3560. Rogue Wave          Virtual Streams  56
  3561.  
  3562.  
  3563.  
  3564.  
  3565.  
  3566.  
  3567.  
  3568.  
  3569.                         USER'S GUIDE
  3570.  
  3571.           The basic abstraction of the virtual streams facility is that
  3572.           builtins are "inserted" into a virtual output stream, "extracted"
  3573.           from a virtual input stream, without any regard for formatting.  That
  3574.           is, there is no need to pad output with whitespace, commas, or any
  3575.           other kind of formatting.  You are effectively telling RWvostream,
  3576.           "Here is a double.  Please store it for me in whatever format is
  3577.           convenient and give it back to me in good shape when I ask for it".
  3578.  
  3579.           The results are extremely powerful.  You can not only use, but also
  3580.           write, saveOn() and restoreFrom() functions without knowing anything
  3581.           about the final output medium or formatting that is to be used.  For
  3582.           example, the output medium could be a disk, memory allocation, or
  3583.           even a network.  The formatting could be in binary, ascii, or network
  3584.           packet.  In all of these cases, the same saveOn() and restoreFrom()
  3585.           functions can be used.
  3586.  
  3587.  
  3588.  
  3589.  
  3590.  
  3591.  
  3592.  
  3593.  
  3594.  
  3595.  
  3596.  
  3597.  
  3598.  
  3599.  
  3600.  
  3601.  
  3602.  
  3603.  
  3604.  
  3605.  
  3606.  
  3607.  
  3608.  
  3609.  
  3610.  
  3611.  
  3612.  
  3613.  
  3614.  
  3615. Rogue Wave          Virtual Streams  57
  3616.  
  3617.  
  3618.  
  3619.  
  3620.  
  3621.  
  3622.  
  3623.  
  3624.                         USER'S GUIDE
  3625.  
  3626.  
  3627. 9.1  Specializing virtual streams
  3628.  
  3629.  
  3630.  
  3631.           The Rogue Wave classes come with two types of classes that specialize
  3632.           RWvistream and RWvostream, one that uses a "portable ASCII"
  3633.           formatting, the other a binary formatting:
  3634.  
  3635.  
  3636.  
  3637.                                     Input class         Output class
  3638.  
  3639.  
  3640.           Abstract base class       RWvistream          RWvostream
  3641.  
  3642.           Portable ASCII            RWpistream          RWpostream
  3643.  
  3644.           Binary                    RWbistream          RWbostream
  3645.  
  3646.  
  3647.  
  3648.  
  3649.           The "portable ASCII" versions store their inserted items in an ASCII
  3650.           format that escapes special characters such as tabs, newlines, etc.,
  3651.           in such a manner that they will be restored properly, even under a
  3652.           new operating system.  The "binary" versions do not reformat their
  3653.           inserted items and, instead, store them in their native format.  For
  3654.           more information, see the respective entries in Part II: Class
  3655.           Reference.
  3656.  
  3657.  
  3658. 9.2  Simple example
  3659.  
  3660.  
  3661.  
  3662.           Here's a simple example that exercises RWbostream and RWbistream
  3663.           through their respective abstract base classes, RWvostream and
  3664.           RWvistream:
  3665.  
  3666.             #include <bstream.h>
  3667.             #include <fstream.h>
  3668.             #include <rwstring.h>
  3669.  
  3670. Rogue Wave          Virtual Streams  58
  3671.  
  3672.  
  3673.  
  3674.  
  3675.  
  3676.  
  3677.  
  3678.  
  3679.                         USER'S GUIDE
  3680.  
  3681.             void save(RWString& a, RWvostream& v)
  3682.             {
  3683.               a.saveOn(v);  // Save to virtual output stream
  3684.             }
  3685.  
  3686.             RWString recover(RWvistream& v)
  3687.             {
  3688.               RWString dupe;
  3689.               dupe.restoreFrom(v);
  3690.               return dupe;
  3691.             }
  3692.  
  3693.             main()
  3694.             {
  3695.               RWString a("A string with\ttabs and a\nnewline.");
  3696.  
  3697.               {
  3698.                 ofstream f("junk.dat", ios::out);       // 1
  3699.                 RWbostream bostr(f);                    // 2
  3700.                 save(a, bostr);
  3701.               }                                         // 3
  3702.  
  3703.               ifstream f("junk.dat", ios::in);          // 4
  3704.               RWbistream bistr(f);                      // 5
  3705.               RWString b = recover(bistr);              // 6
  3706.  
  3707.               cout << a << NL;  // Compare the two strings// 7
  3708.               cout << b << NL;
  3709.             }
  3710.  
  3711.           Program output:
  3712.  
  3713.             A string with   tabs and a
  3714.             newline.
  3715.             A string with   tabs and a
  3716.             newline.
  3717.  
  3718.           The job of function save(RWString& a, RWvostream& v) is to save the
  3719.           string a to the virtual output stream v.  Function
  3720.           recover(RWvistream&) restores the results.  These functions do not
  3721.           know the ultimate format with which the string will be stored.  Some
  3722.           additional comments on particular lines:
  3723.  
  3724.           1  On this line, a file output stream f is created for the file
  3725. Rogue Wave          Virtual Streams  59
  3726.  
  3727.  
  3728.  
  3729.  
  3730.  
  3731.  
  3732.  
  3733.  
  3734.                         USER'S GUIDE
  3735.  
  3736.              "junk.dat".
  3737.  
  3738.           2  On this line, a RWbostream is created from f.
  3739.  
  3740.           3  Because this clause in enclosed in brackets { ... }, the
  3741.              destructor for f will be called here.  This will cause the file
  3742.              to be closed.
  3743.  
  3744.           4  The file is reopened, this time for input.
  3745.  
  3746.           5  Now a RWbistream is created from it.
  3747.  
  3748.           6  The string is recovered from the file.
  3749.  
  3750.           7  Finally, both the original and recovered strings are printed for
  3751.              comparison.
  3752.  
  3753.           This program could be simplified by using class fstream, which
  3754.           multiply inherits ofstream and ifstream, for both output and input.
  3755.           A seek to beginning-of-file would occur before reading the results
  3756.           back in.  Unfortunately, at the time of this writing, most
  3757.           implementations of seekg() have not proven to be reliable.  Hence,
  3758.           this approach was not chosen for this example.
  3759.  
  3760.  
  3761.  
  3762.  
  3763.  
  3764.  
  3765.  
  3766.  
  3767.  
  3768.  
  3769.  
  3770.  
  3771.  
  3772.  
  3773.  
  3774.  
  3775.  
  3776.  
  3777.  
  3778.  
  3779.  
  3780. Rogue Wave          Virtual Streams  60
  3781.  
  3782.  
  3783.  
  3784.  
  3785.  
  3786.  
  3787.  
  3788.  
  3789.                         USER'S GUIDE
  3790.  
  3791.  
  3792. 9.3  Windows_ Clipboard and DDE streambufs
  3793.  
  3794.  
  3795.  
  3796.           Class "streambuf" is the underlying "sequencing" layer of the
  3797.           iostreams facility.  It is responsible for producing and consuming
  3798.           sequences of characters.  Your compiler comes with several versions.
  3799.           For example, class filebuf ultimately gets and puts its characters to
  3800.           a file.  Class strstreambuf gets and puts to memory-based character
  3801.           streams (you can think of it as the iostream equivalent to ANSI-C's
  3802.           sprintf() function).  Now Tools.h++ adds two Windows-based
  3803.           extensions:
  3804.  
  3805.           o  Class RWCLIPstreambuf for getting and putting to the Clipboard;
  3806.  
  3807.           o  Class RWDDEstreambuf for getting and putting through the DDE
  3808.              facility.
  3809.  
  3810.           They take care of the details of allocating and reallocating memory
  3811.           from Windows as buffers are over- and underflowed.  In the case of
  3812.           class RWDDEstreambuf, the associated DDEDATA header is also filled in
  3813.           for you.  Any class that inherits from class ios can be used with
  3814.           these streambufs.  This includes the familiar istream and ostream, as
  3815.           well as the Rogue Wave virtual stream classes.
  3816.  
  3817.  
  3818. 9.4  DDE example
  3819.  
  3820.  
  3821.  
  3822.           Let's look at a more complicated example: how one might exchange a
  3823.           SortedCollection through the Windows DDE facility (a similar
  3824.           technique can be used for Window's Clipboard), using class
  3825.           RWDDEstreambuf.
  3826.  
  3827.             #include <bintree.h>
  3828.             #include <collstr.h>
  3829.             #include <bstream.h>
  3830.             #include <winstream.h>
  3831.             #include <windows.h>
  3832.             #include <dde.h>
  3833.  
  3834.  
  3835. Rogue Wave          Virtual Streams  61
  3836.  
  3837.  
  3838.  
  3839.  
  3840.  
  3841.  
  3842.  
  3843.  
  3844.                         USER'S GUIDE
  3845.  
  3846.             BOOL
  3847.             PostCollection(HWND hwndServer, WORD cFormat)
  3848.             {
  3849.               SortedCollection sc;                      // 1
  3850.               sc.insert(new RWCollectableString("Mary"));
  3851.               sc.insert(new RWCollectableString("Bill"));
  3852.               sc.insert(new RWCollectableString("Pierre"));
  3853.  
  3854.               // Allocate a RWDDEstreambuf and use it to initialize
  3855.               // a RWbostream:
  3856.               RWDDEstreambuf* sbuf = new RWDDEstreambuf(cFormat);     // 2
  3857.               RWbostream bostr( sbuf );                 // 3
  3858.  
  3859.               // Store the collection to the RWbostream:
  3860.               sc.saveOn(bostr);                         // 4
  3861.  
  3862.               // Lock the output stream, and get its handle:
  3863.               HANDLE hDDEData = sbuf->str();            // 5
  3864.  
  3865.               // Get an atom to identify the DDE Message:
  3866.               ATOM atom = GlobalAddAtom("SortedNames"); // 6
  3867.  
  3868.               // Post the DDE response:
  3869.               return PostMessage(0xFFFF, WM_DDE_DATA, hwndServer,     // 7
  3870.                          MAKELONG(hDDEData, atom));
  3871.             }
  3872.  
  3873.           The large memory model has been assumed.  Here's the line-by-line
  3874.           description:
  3875.  
  3876.           1  A SortedCollection is built and some items inserted into it.
  3877.  
  3878.           2  An RWDDEstreambuf is allocated.  The constructor takes several
  3879.              arguments.  Here, all of the default arguments were used except
  3880.              for the first, the Windows clipboard format.  In this example,
  3881.              the format type has been passed in as an argument, but in
  3882.              general, you will probably want to register a format with Windows
  3883.              (using RegisterClipboardFormat()) and then use that.
  3884.  
  3885.              The other, default, arguments have to do with the intricacies of
  3886.              DDE data exchange acknowledgments and memory management.  See
  3887.              Part II, Class Reference for the list of arguments and, for
  3888.              example, Petzold (1990), Chapter 17, or the Microsoft Windows
  3889.              Guide to Programming, Chapter 22, for their meanings.
  3890. Rogue Wave          Virtual Streams  62
  3891.  
  3892.  
  3893.  
  3894.  
  3895.  
  3896.  
  3897.  
  3898.  
  3899.                         USER'S GUIDE
  3900.  
  3901.           3  An RWbostream is constructed from the supplied RWDDEstreambuf.
  3902.              We could have used an RWpostream here, but DDE exchanges are done
  3903.              within the same machine architecture so, presumably, it is not
  3904.              worth the extra overhead of using the portable ASCII formats.
  3905.              Nevertheless, note how the disposition of the bytes (which is set
  3906.              by the type of streambuf) is cleanly separated from their
  3907.              formatting, which is set by the type of RWvostream.
  3908.  
  3909.           4  The collection is saved to the RWbostream.  Because the
  3910.              RWbostream's associated streambuf is actually an RWDDEstreambuf,
  3911.              the collection is actually being saved to a Window's global
  3912.              memory allocation with characteristic GMEM_DDESHARE.  This
  3913.              allocation is automatically resized if it is overflowed.  Like
  3914.              any other strstreambuf, you can change the size of the allocation
  3915.              chunks using member function setbuf().
  3916.  
  3917.           5  The RWDDEstreambuf is locked.  Once locked using str(), this
  3918.              streambuf, like any other strstreambuf, cannot be used again.
  3919.              Note, however, that RWDDEstreambuf::str() returns a handle,
  3920.              rather than a char*.  The handle is unlocked before returning it.
  3921.  
  3922.           6  An atom is constructed to identify this DDE data.
  3923.  
  3924.           7  The handle returned by RWDDEstreambuf::str(), along with its
  3925.              identifying atom, is posted.
  3926.  
  3927.           A similar (actually, simpler) technique can be used for Clipboard
  3928.           exchanges.
  3929.  
  3930.           Note that there is nothing that constrains you to using the
  3931.           specialized streambufs RWDLIPstreambuf and RWDDEstreambuf with only
  3932.           the Rogue Wave virtual streams facility.  One could quite easily use
  3933.           them with regular istreams and ostreams.  You just wouldn't be able
  3934.           to set the formatting at runtime.
  3935.  
  3936.  
  3937. 9.5  Recap
  3938.  
  3939.  
  3940.  
  3941.           We have seen how an object can be stored and recovered from streams
  3942.           without regard to the final destination of the bytes of that stream.
  3943.           They could reside in memory, or on disk.  We have also seen how we
  3944.           need not be concerned with the final formatting of the stream.  It
  3945. Rogue Wave          Virtual Streams  63
  3946.  
  3947.  
  3948.  
  3949.  
  3950.  
  3951.  
  3952.  
  3953.  
  3954.                         USER'S GUIDE
  3955.  
  3956.           could be in ASCII or binary.
  3957.  
  3958.           It is also quite possible to write your own specializing "virtual
  3959.           stream" class, much like RWpostream and RWpistream, that could, for
  3960.           example, "store" an object to a network, perhaps using an XDR format.
  3961.           The great advantage of the virtual streams facility is that if you do
  3962.           write your own specialized virtual stream, there is no need to modify
  3963.           any of the code of the client classes -- you just use your stream
  3964.           class as an argument to saveOn(RWvostream&) and
  3965.           restoreFrom(RWvistream&).
  3966.  
  3967.           In addition to storing and retrieving an object to and from virtual
  3968.           streams, all of the classes can store and retrieve themselves in
  3969.           binary to and from an RWFile.  This file encapsulates ANSI-C style
  3970.           file I/O.  Although more limited in its abilities than stream I/O,
  3971.           this form of storage and retrieval is faster to and from disk because
  3972.           the virtual dispatching machinery is not needed.
  3973.  
  3974.  
  3975.  
  3976.  
  3977.  
  3978.  
  3979.  
  3980.  
  3981.  
  3982.  
  3983.  
  3984.  
  3985.  
  3986.  
  3987.  
  3988.  
  3989.  
  3990.  
  3991.  
  3992.  
  3993.  
  3994.  
  3995.  
  3996.  
  3997.  
  3998.  
  3999.  
  4000. Rogue Wave          Virtual Streams  64
  4001.  
  4002.  
  4003.  
  4004.  
  4005.  
  4006.  
  4007.  
  4008.  
  4009.  
  4010.  
  4011.  
  4012.  
  4013.  
  4014.  
  4015.  
  4016.                                                           S e c t i o n    1 0 
  4017.  
  4018.  
  4019.                                                        Using Class RWFileRWFile
  4020.  
  4021.  
  4022.  
  4023.           Class RWFile encapsulates the standard C file operations for binary
  4024.           read and write, using the ANSI-C function  fopen(), fwrite(),
  4025.           fread(), etc.  This class is based on class PFile of the Interviews
  4026.           Class Library (1987, Stanford University), but has been modified (and
  4027.           modernized) by Rogue Wave to use "const" modifiers, and to port to
  4028.           MS-DOS.  The member function names begin with upper case letters in
  4029.           order to maintain compatibility with class PFile.
  4030.  
  4031.           The constructor for class RWFile has prototype
  4032.  
  4033.             RWFile(const char* filename);
  4034.  
  4035.           This constructor will open a binary file called filename for
  4036.           read/write, creating it if it does not already exist.  The destructor
  4037.           for this class closes the file.
  4038.  
  4039.           There are member functions for flushing the file, and for testing
  4040.           whether the file is empty, has had an error, or is at the end-of-
  4041.           file.
  4042.  
  4043.  
  4044. 10.1 Example
  4045.  
  4046.  
  4047.  
  4048.           Class RWFile has member functions to determine the status of a file,
  4049.           and to read and write a wide variety of built in types, either one at
  4050.           a time, or from and into blocks of n instances of a built-in type.
  4051.           The file pointer may be repositioned with functions SeekTo(),
  4052.           SeekToBegin(), and SeekToEnd().  The details of the RWFile class
  4053.           capabilities are summarized in Part II: Class Reference.
  4054.  
  4055. Rogue Wave         Using Class RWFile  65
  4056.  
  4057.  
  4058.  
  4059.  
  4060.  
  4061.  
  4062.  
  4063.  
  4064.                         USER'S GUIDE
  4065.  
  4066.           For example, to create a RWFile with filename "test.dat", read an int
  4067.           (if the file is not empty), increment it, and write it back to the
  4068.           file:
  4069.  
  4070.             #include <rwfile.h>
  4071.  
  4072.             main()
  4073.             {
  4074.                RWFile file("test.dat");      // Construct the RWFile.
  4075.  
  4076.                // Check that the file exists, and that it has
  4077.                // read/write permission:
  4078.                if ( file.Exists() ) {
  4079.                     int i;
  4080.                     // Read the int if the file is not empty:
  4081.                     if ( !file.IsEmpty() ) file.Read(i);
  4082.                     i++;
  4083.                     file.SeekToBegin();
  4084.                     file.Write(i);      // Rewrite the int.
  4085.                }
  4086.             }
  4087.  
  4088.  
  4089.  
  4090.  
  4091.  
  4092.  
  4093.  
  4094.  
  4095.  
  4096.  
  4097.  
  4098.  
  4099.  
  4100.  
  4101.  
  4102.  
  4103.  
  4104.  
  4105.  
  4106.  
  4107.  
  4108.  
  4109.  
  4110. Rogue Wave         Using Class RWFile  66
  4111.  
  4112.  
  4113.  
  4114.  
  4115.  
  4116.  
  4117.  
  4118.  
  4119.  
  4120.  
  4121.  
  4122.  
  4123.  
  4124.  
  4125.  
  4126.                                                           S e c t i o n    1 1 
  4127.  
  4128.  
  4129.                                          Using Class RWFileManagerRWFileManager
  4130.  
  4131.  
  4132.  
  4133.           Class RWFileManager allocates, deallocates and coalesces free space
  4134.           in a disk file.  This is done internally by maintaining on disk a
  4135.           linked-list of free space blocks.
  4136.  
  4137.           Two typedefs are used:
  4138.  
  4139.             typedef long      RWoffset;
  4140.             typedef unsigned  RWspace;
  4141.  
  4142.           The type RWoffset is used for the offset within the file to the start
  4143.           of a storage space; RWspace is the amount of storage space required.
  4144.           The actual typedef may vary depending on the system you are using.
  4145.  
  4146.           Class RWFile is a public base class of class RWFileManager, therefore
  4147.           the public member functions of class RWFile are available to class
  4148.           RWFileManager.
  4149.  
  4150.  
  4151. 11.1 Construction
  4152.  
  4153.  
  4154.  
  4155.           The RWFileManager constructor has prototype:
  4156.  
  4157.             RWFileManager(const char* filename);
  4158.  
  4159.           The first argument is the name of the file that the RWFileManager is
  4160.           to manage.  If a new file is specified, it will be initialized
  4161.           properly.  Otherwise, if the file is not empty, the old data will be
  4162.           read.  In this case, the data on the file must have been previously
  4163.           written by a RWFileManager.
  4164.  
  4165. Rogue Wave     Using Class RWFileManager  67
  4166.  
  4167.  
  4168.  
  4169.  
  4170.  
  4171.  
  4172.  
  4173.  
  4174.                         USER'S GUIDE
  4175.  
  4176.  
  4177. 11.2 Member functions
  4178.  
  4179.  
  4180.  
  4181.           The class RWFileManager adds four additional member functions to
  4182.           those of class RWFile. They are:
  4183.  
  4184.           1. RWoffset allocate(RWspace s);
  4185.  
  4186.              Allocate s bytes of storage in the file, returning the offset to
  4187.              the start of the allocation.
  4188.  
  4189.           2. void deallocate(RWoffset t);
  4190.  
  4191.              Deallocate (free) the storage space starting at offset t.  This
  4192.              space must have been previously allocated by the function
  4193.              allocate():
  4194.  
  4195.           3. RWOffset endData();
  4196.  
  4197.              Return the offset to the last data in the file.
  4198.  
  4199.           4. RWoffset start();
  4200.  
  4201.              Return the offset from the start of the file to the first space
  4202.              ever allocated by this RWFileManager, or return NIL4 if no space
  4203.              has been allocated, implying that this is a "newFile".
  4204.  
  4205.           The statement
  4206.  
  4207.             RWoffset a = F.allocate(sizeof(double));
  4208.  
  4209.           uses RWFileManager F to allocate the space required to store an
  4210.           object with the size of a double and returns the offset to that
  4211.           space.  To write the object to the disk file, you should use Write().
  4212.           It is also your responsibility to maintain a record of the offsets
  4213.           necessary to read the stored object.
  4214.  
  4215.                     
  4216.  
  4217.           4    NIL is a macro whose actual value is system dependent.
  4218.                Typically, it is -1L.
  4219.  
  4220. Rogue Wave     Using Class RWFileManager  68
  4221.  
  4222.  
  4223.  
  4224.  
  4225.  
  4226.  
  4227.  
  4228.  
  4229.                         USER'S GUIDE
  4230.  
  4231.           To help you do this, the first allocation ever made by a
  4232.           RWFileManager is considered "special"and can be returned by member
  4233.           function start() at any time.  The RWFileManager will not allow you
  4234.           to deallocate it.  This first block will typically hold information
  4235.           necessary to read the remaining data, perhaps the offset of a root
  4236.           node, or the head of a linked-list.
  4237.  
  4238.           The following example shows the use of class RWFileManager to
  4239.           construct a linked-list of ints on disk:  The source code is included
  4240.           in the toolexam subdirectory as example7.cpp and example8.cpp.
  4241.  
  4242.  
  4243.             #include <filemgr.h>                        // 1
  4244.             #include <rstream.h>
  4245.  
  4246.             struct DiskNode {                           // 2
  4247.                  int      data;                         // 3
  4248.                  RWoffset nextNode;                     // 4
  4249.             };
  4250.  
  4251.             main()
  4252.             {
  4253.                 RWFileManager fm("linklist.dat");       // 5
  4254.  
  4255.                 // Allocate space for offset to start of the linked list:
  4256.                 fm.allocate(sizeof(RWoffset));          // 6
  4257.                 // Allocate space for the first link:
  4258.                 RWoffset thisNode = fm.allocate(sizeof(DiskNode));    // 7
  4259.  
  4260.                 fm.SeekTo(fm.start());                  // 8
  4261.                  fm.Write(thisNode);                    // 9
  4262.  
  4263.                  DiskNode n;
  4264.                  int temp;
  4265.                  RWoffset lastNode;
  4266.                  cout << "Input a series of integers, then EOF to end:\n";
  4267.  
  4268.  
  4269.  
  4270.  
  4271.  
  4272.  
  4273.  
  4274.  
  4275. Rogue Wave     Using Class RWFileManager  69
  4276.  
  4277.  
  4278.  
  4279.  
  4280.  
  4281.  
  4282.  
  4283.  
  4284.                         USER'S GUIDE
  4285.  
  4286.                  while (cin >> temp) {                 // 10
  4287.                    n.data = temp;
  4288.                    n.nextNode = fm.allocate(sizeof(DiskNode));   // 11
  4289.                    fm.SeekTo(thisNode);                // 12
  4290.                    fm.Write(n.data);                   // 13
  4291.                    fm.Write(n.nextNode);
  4292.                    lastNode = thisNode;                // 14
  4293.                    thisNode = n.nextNode;
  4294.                  }
  4295.  
  4296.                  fm.deallocate(n.nextNode);            // 15
  4297.                  n.nextNode = NIL;                     // 16
  4298.                  fm.SeekTo(lastNode);
  4299.                  fm.Write(n.data);
  4300.                  fm.Write(n.nextNode);
  4301.             }                                          // 17
  4302.  
  4303.           Here's a line-by-line description of the program:
  4304.  
  4305.           1  Include the declarations for the class RWFileManager.  The header
  4306.              file <rstream.h> includes either <iostream.h> or <stream.h> for
  4307.              input and output , depending on your compiler.  See Section 4.
  4308.  
  4309.           2  Struct DiskNode is a link in the linked-list.  It contains:
  4310.  
  4311.           3  The data (an int), and
  4312.  
  4313.           4  The offset to the next link.  RWoffset is typically "typedef'd"
  4314.              to a long int.
  4315.  
  4316.           5  This is the constructor for a RWFileManager.  It will create a
  4317.              new file, called "linklist.dat".
  4318.  
  4319.           6  Allocate space on the file to store the offset to the first link.
  4320.              This first allocation is considered "special" and will be saved
  4321.              by the RWFileManager.  It can be retrieved at any time by using
  4322.              the member function start().
  4323.  
  4324.           7  Allocate space to store the first link.  The member function
  4325.              allocate() returns the offset to this space.  Since each DiskNode
  4326.              needs the offset to the next DiskNode, space for the next link
  4327.              must be allocated before the current link is written.
  4328.  
  4329.           8  Seek to the position to write the offset to the first link.  Note
  4330. Rogue Wave     Using Class RWFileManager  70
  4331.  
  4332.  
  4333.  
  4334.  
  4335.  
  4336.  
  4337.  
  4338.  
  4339.                         USER'S GUIDE
  4340.  
  4341.              that the offset to this position is returned by the member
  4342.              function start().  Note also that fm has access to public member
  4343.              functions of class RWFile, since class RWFileManager is derived
  4344.              from class RWFile.
  4345.  
  4346.           9  Write the offset to the first link.
  4347.  
  4348.           10 A loop to read integers and store them in a linked-list5.
  4349.  
  4350.           11 Allocate space for the next link, storing the offset to it in the
  4351.              nextNode field of this link.
  4352.  
  4353.           12 Seek to the proper offset to store this link
  4354.  
  4355.           13 Write this link.
  4356.  
  4357.           14 Since we allocate the next link before we write the current link,
  4358.              the final link in the list will have an offset to an allocated
  4359.              block that is not used. It must be handled as a special case.
  4360.  
  4361.           15 First, deallocate the final unused block.
  4362.  
  4363.           16 Next, reassign the offset of the final link to be NIL.  When the
  4364.              list is read, this will indicate the end of the linked list.
  4365.              Finally, re-write the final link, with the correct information.
  4366.  
  4367.           17 The destructor for class RWFileManager, which closes the file,
  4368.              will be called here.
  4369.  
  4370.           Having created the linked-list on disk, how might we read it?  Here
  4371.           is a program that reads the list and prints the stored integer field.
  4372.  
  4373.             #include <filemgr.h>
  4374.             #include <rstream.h>
  4375.  
  4376.  
  4377.  
  4378.                     
  4379.  
  4380.           5    This loop will not work as written with the Turbo C++
  4381.                V1.00 compiler due to a bug in the compiler.  The stream
  4382.                state must be tested explicitly with member function
  4383.                good().
  4384.  
  4385. Rogue Wave     Using Class RWFileManager  71
  4386.  
  4387.  
  4388.  
  4389.  
  4390.  
  4391.  
  4392.  
  4393.  
  4394.                         USER'S GUIDE
  4395.  
  4396.             struct DiskNode {
  4397.                  int      data;
  4398.                  RWoffset nextNode;
  4399.             };
  4400.  
  4401.             main()
  4402.             {
  4403.                  RWFileManager fm("linklist.dat");      // 1
  4404.  
  4405.                  fm.SeekTo(fm.start());                 // 2
  4406.                  RWoffset next;
  4407.                  fm.Read(next);                         // 3
  4408.  
  4409.                  DiskNode n;
  4410.                  while (next != NIL) {                  // 4
  4411.                     fm.SeekTo(next);                    // 5
  4412.                     fm.Read(n.data);                    // 6
  4413.                     fm.Read(n.nextNode);
  4414.                     cout << n.data << "\n";             // 7
  4415.                     next = n.nextNode;                  // 8
  4416.                     }
  4417.             }                                           // 9
  4418.  
  4419.           Here's a line-by-line description of the program:
  4420.           1  The RWFileManager has been constructed with an old File.
  4421.           2  The member function start() returns the offset to the first space
  4422.              ever allocated in the file.  In this case, that space will
  4423.              contain an offset to the start of the linked-list.
  4424.           3  Read the offset to the first link.
  4425.           4  A loop to read through the linked-list and print each entry.
  4426.           5  Seek to the next link.
  4427.           6  Read the next link.
  4428.           7  Print the integer.
  4429.           8  Get the offset to the next link.
  4430.           9  The destructor for class RWFileManager, which closes the file,
  4431.              will be called here.
  4432.  
  4433.  
  4434.  
  4435.  
  4436.  
  4437.  
  4438.  
  4439.  
  4440. Rogue Wave     Using Class RWFileManager  72
  4441.  
  4442.  
  4443.  
  4444.  
  4445.  
  4446.  
  4447.  
  4448.  
  4449.  
  4450.  
  4451.  
  4452.  
  4453.  
  4454.  
  4455.  
  4456.                                                           S e c t i o n    1 2 
  4457.  
  4458.  
  4459.                                          Using Class RWBTreeOnDiskRWBTreeOnDisk
  4460.  
  4461.  
  4462.  
  4463.           Class RWBTreeOnDisk has been designed to manage a B-Tree in a disk
  4464.           file.  The class represents an ordered collection of associations of
  4465.           keys and values, where the ordering is determined internally by
  4466.           comparing keys.  Given a key, a value can be retrieved.  Duplicate
  4467.           keys are not allowed.
  4468.  
  4469.           Keys are arrays of chars.  Nominally, they can have up to 16
  4470.           characters, although this can be changed by recompiling.  The
  4471.           ordering in the B-Tree is determined by comparing keys
  4472.           lexicographically.
  4473.  
  4474.           The type of the values is set by a typedef.  By default, this is:
  4475.  
  4476.             typedef long storedValue;
  4477.  
  4478.           Typically, the values represent an offset to a location in a file
  4479.           where an object is stored.  Hence, given a key, one can find where an
  4480.           object is stored and retrieve it.  However, as far as class
  4481.           RWBTreeOnDisk is concerned, the value has no special meaning -- it is
  4482.           up to you to interpret it.
  4483.  
  4484.           This class uses class RWFileManager to manage the allocation and
  4485.           deallocation of space for the nodes of the B-Tree.  The same
  4486.           RWFileManager can also be used to manage the space for the objects
  4487.           themselves if the B-Tree and data are to be in the same file.
  4488.           Alternatively, a different RWFileManager, managing a different file,
  4489.           could be used if it is desirable to store the B-Tree and data in
  4490.           separate files.
  4491.  
  4492.           The member functions associated with class RWBTreeOnDisk are
  4493.           identical to those of class RWBTree, which manages a B-Tree in
  4494.           memory, except that keys are arrays of chars rather than
  4495. Rogue Wave     Using Class RWBTreeOnDisk  73
  4496.  
  4497.  
  4498.  
  4499.  
  4500.  
  4501.  
  4502.  
  4503.  
  4504.                         USER'S GUIDE
  4505.  
  4506.           RWCollectable*'s.  There are member functions to add a key-value
  4507.           pair, find a key, remove a key,  operate on all key-value pairs in
  4508.           order, determine the height of the tree, return the number of entries
  4509.           in the tree,  and determine if a key is contained in the tree.
  4510.  
  4511.  
  4512.  
  4513.  
  4514.  
  4515.  
  4516.  
  4517.  
  4518.  
  4519.  
  4520.  
  4521.  
  4522.  
  4523.  
  4524.  
  4525.  
  4526.  
  4527.  
  4528.  
  4529.  
  4530.  
  4531.  
  4532.  
  4533.  
  4534.  
  4535.  
  4536.  
  4537.  
  4538.  
  4539.  
  4540.  
  4541.  
  4542.  
  4543.  
  4544.  
  4545.  
  4546.  
  4547.  
  4548.  
  4549.  
  4550. Rogue Wave     Using Class RWBTreeOnDisk  74
  4551.  
  4552.  
  4553.  
  4554.  
  4555.  
  4556.  
  4557.  
  4558.  
  4559.                         USER'S GUIDE
  4560.  
  4561.  
  4562. 12.1 Construction
  4563.  
  4564.  
  4565.  
  4566.           A RWBTreeOnDisk is always constructed from a RWFileManager.  If the
  4567.           RWFileManager is managing a "newFile", then the RWBTreeOnDisk will
  4568.           initialize it with an empty root node.  For example, the following
  4569.           code fragment constructs a RWFileManager for a new file called
  4570.           "filename.dat" and then constructs a RWBTreeOnDisk from it:
  4571.  
  4572.             #include <disktree.h>
  4573.             #include <filemgr.h>
  4574.  
  4575.             main()
  4576.             {
  4577.                  RWFileManager fm("filename.dat");
  4578.  
  4579.                  // Initializes filename.dat with an empty root:
  4580.                  RWBTreeOnDisk bt(fm);
  4581.             }
  4582.  
  4583. 12.2 Example
  4584.  
  4585.  
  4586.  
  4587.           In this example, key-value pairs of character strings and offsets to
  4588.           RWDates, representing birthdays, are stored.  Given a name, a
  4589.           birthdate can be retrieved from disk.
  4590.  
  4591.  
  4592.  
  4593.  
  4594.  
  4595.  
  4596.  
  4597.  
  4598.  
  4599.  
  4600.  
  4601.  
  4602.  
  4603.  
  4604.  
  4605. Rogue Wave     Using Class RWBTreeOnDisk  75
  4606.  
  4607.  
  4608.  
  4609.  
  4610.  
  4611.  
  4612.  
  4613.  
  4614.                         USER'S GUIDE
  4615.  
  4616.             #include "disktree.h"
  4617.             #include "filemgr.h"
  4618.             #include "rwdate.h"
  4619.             #include <iostream.h>
  4620.             #include <iomanip.h>
  4621.  
  4622.             main()
  4623.             {
  4624.               char name[16];
  4625.               RWDate birthday;
  4626.  
  4627.               RWFileManager fm("birthday.dat");
  4628.               RWBTreeOnDisk btree(fm);
  4629.  
  4630.               while(cin >> setw(sizeof(name)) >> name) {// 1
  4631.                 cin >> birthday;                        // 2
  4632.                 RWoffset loc = fm.allocate(birthday.binaryStoreSize());    // 3
  4633.                 fm.SeekTo(loc);                         // 4
  4634.                 birthday.saveOn(&fm);                   // 5
  4635.                 btree.insertKeyAndValue(name, loc);     // 6
  4636.               }
  4637.             }
  4638.  
  4639.           Here's the line-by-line description:
  4640.  
  4641.           1  Read the name from standard input.  This loop will exit when EOF
  4642.              is reached.  The object setw() is an "I/O manipulator", a feature
  4643.              of the new "Version 2.0 style" iostreams.  It insures that no
  4644.              more than 16 characters will be read.
  4645.  
  4646.           2  Read the corresponding birthday.
  4647.  
  4648.           3  Allocate enough space from the RWFileManager to store the
  4649.              birthday.  Member function binaryStoreSize() is a member function
  4650.              that most Rogue Wave classes have.  It returns the number of
  4651.              bytes necessary to store an object in a binary file.
  4652.  
  4653.           4  Seek to the location where the RWDate will be stored.
  4654.  
  4655.           5  Store the date at that location.  Member function saveOn() is a
  4656.              member function that most Rogue Wave classes have.  It stores the
  4657.              object in a binary file or on an ostream, depending on the type
  4658.              of its argument.
  4659.  
  4660. Rogue Wave     Using Class RWBTreeOnDisk  76
  4661.  
  4662.  
  4663.  
  4664.  
  4665.  
  4666.  
  4667.  
  4668.  
  4669.                         USER'S GUIDE
  4670.  
  4671.           6  Insert the key and offset to the object in the B-Tree.
  4672.  
  4673.           Having stored the names and birthdates on a file, here's how one
  4674.           might retrieve them:
  4675.  
  4676.             #include "disktree.h"
  4677.             #include "filemgr.h"
  4678.             #include "rwdate.h"
  4679.             #include <iostream.h>
  4680.             #include <iomanip.h>
  4681.  
  4682.             main()
  4683.             {
  4684.               char name[16];
  4685.               RWDate birthday;
  4686.               RWFileManager fm("birthday.dat");
  4687.               RWBTreeOnDisk btree(fm);
  4688.               RWoffset loc;
  4689.  
  4690.               while(1){
  4691.                cout << "Give name: ";
  4692.                if ( !(cin >> setw(sizeof(name)) >> name) ) break;     // 1
  4693.                btree.findKeyAndValue(name, loc);        // 2
  4694.                if( loc==NIL )                           // 3
  4695.                   cerr << "Not found.\n";
  4696.                else {
  4697.                   fm.SeekTo(loc);                       // 4
  4698.                   birthday.restoreFrom(&fm);            // 5
  4699.                   cout << "Birthday is " << birthday << NL;// 6
  4700.                 }
  4701.               }
  4702.             }
  4703.  
  4704.           Program description:
  4705.  
  4706.           1  The program accepts names until encountering an EOF.
  4707.  
  4708.           2  The name is used as a key to the RWBTreeOnDisk, which returns the
  4709.              associated value, an offset into the file.
  4710.  
  4711.           3  Check to see whether the name was found.
  4712.  
  4713.           4  If the name was valid, use the value to seek to the spot where
  4714.              the associated birthday is stored.
  4715. Rogue Wave     Using Class RWBTreeOnDisk  77
  4716.  
  4717.  
  4718.  
  4719.  
  4720.  
  4721.  
  4722.  
  4723.  
  4724.                         USER'S GUIDE
  4725.  
  4726.           5  Read the birthdate from the file.
  4727.  
  4728.           6  Print it out.
  4729.  
  4730.  
  4731.  
  4732.  
  4733.  
  4734.  
  4735.  
  4736.  
  4737.  
  4738.  
  4739.  
  4740.  
  4741.  
  4742.  
  4743.  
  4744.  
  4745.  
  4746.  
  4747.  
  4748.  
  4749.  
  4750.  
  4751.  
  4752.  
  4753.  
  4754.  
  4755.  
  4756.  
  4757.  
  4758.  
  4759.  
  4760.  
  4761.  
  4762.  
  4763.  
  4764.  
  4765.  
  4766.  
  4767.  
  4768.  
  4769.  
  4770. Rogue Wave     Using Class RWBTreeOnDisk  78
  4771.  
  4772.  
  4773.  
  4774.  
  4775.  
  4776.  
  4777.  
  4778.  
  4779.  
  4780.  
  4781.  
  4782.  
  4783.  
  4784.  
  4785.  
  4786.                                                           S e c t i o n    1 3 
  4787.  
  4788.  
  4789.                Introduction to Collection ClassesCollection classesintroduction
  4790.  
  4791.  
  4792.  
  4793.  
  4794. 13.1 Introduction
  4795.  
  4796.  
  4797.  
  4798.           The Tools.h++ class library has two different types of collection
  4799.           classes:
  4800.  
  4801.           l  A set of "generic" collection classes, modeled after Stroustrup,
  4802.              Chapter 7.3.5.
  4803.  
  4804.  
  4805.           l  A set of Smalltalk -like collection classes.
  4806.  
  4807.           Despite their very different implementations, the functionality of
  4808.           the two sets of classes, as well as the user-interface (member
  4809.           function names, etc.), is very similar.
  4810.  
  4811.  
  4812. 13.1.1Some general concepts
  4813.  
  4814.           The general objective of the collection classes is to store and
  4815.           retrieve pointers to objects.  Hence, when you "insert" an object
  4816.           into a collection, you are actually telling the collection class to
  4817.           store a pointer to it -- the object itself is not actually inserted.
  4818.           The storage and retrieval methods to get this pointer back is what
  4819.           makes each class different.  For example, the linked-lists excel at
  4820.           "inserting" an object in the middle of the collection, but are
  4821.           relatively slow at finding an object (because each link must be
  4822.           searched).  On the other hand, inserting an object into a hash table
  4823.           is slower, but retrieving it can be much faster.  Which class you
  4824.           chose will depend on what is important for the application you have
  4825. Rogue WaveIntroduction to Collection Classes   79
  4826.  
  4827.  
  4828.  
  4829.  
  4830.  
  4831.  
  4832.  
  4833.  
  4834.                         USER'S GUIDE
  4835.  
  4836.           in mind.
  4837.  
  4838.           In general, you are responsible for the creation, maintenance and
  4839.           destruction of the actual objects themselves, although there are a
  4840.           few member function to help you do this.
  4841.  
  4842.           Now it is time to clarify a few concepts and to identify the jargon
  4843.           you are likely to encounter both here and in the literature.
  4844.  
  4845.  
  4846.           13.1.1.1  An object's identity
  4847.  
  4848.           Every object that you create has three properties associated with it:
  4849.  
  4850.           1. Its "type" (e.g., a RWString or a "double").  In C++, an object's
  4851.              type is set at creation.  It cannot change.
  4852.  
  4853.           2. Its "state" (i.e., the value of the string).  The values of all
  4854.              the instance variables of an object determine its state.  These
  4855.              can change.
  4856.  
  4857.           3. Its "identity" (i.e., identifies an object uniquely and for all
  4858.              time).  In C++, an object's identity is determined by its
  4859.              address.  Each object is associated with one and only one
  4860.              address.  Note that the reverse is not always true because of
  4861.              inheritance.  Generally, an address and a type is necessary to
  4862.              disambiguate which object you mean within an inheritance
  4863.              hierarchy.
  4864.  
  4865.           Note that different languages use different methods for establishing
  4866.           an object's identity.  For example, an object-oriented data base
  4867.           could use an "object ID" to identify a particular object.  It is just
  4868.           a property of C++ that an object's address is used.
  4869.  
  4870.           How an object is "found" within a collection class depends on how you
  4871.           use these three properties.
  4872.  
  4873.  
  4874.  
  4875.           A key point is that there are two general methods for "finding" an
  4876.           object and you will have to keep in mind which you mean.  Some
  4877.           collection classes can support either method, some can support only
  4878.           one.
  4879.  
  4880. Rogue WaveIntroduction To Collection Classes   80
  4881.  
  4882.  
  4883.  
  4884.  
  4885.  
  4886.  
  4887.  
  4888.  
  4889.                         USER'S GUIDE
  4890.  
  4891.           1. Find an object with a particular state.  An example is testing
  4892.              two strings for the same value.  In the literature, this is
  4893.              frequently referred to as two objects testing "isEqual", having
  4894.              "equality", "compares equal", having the same "value", or testing
  4895.              true for the "=" operator.  Here, we will refer to the two
  4896.              objects as testing equal ("isEqual").  In general, it is
  4897.              necessary to have some knowledge of the two object's type (or
  4898.              subtype, in the case of inheritance) in order to find the
  4899.              appropriate instance variables to test for equality6.
  4900.  
  4901.           2. Finding a particular object (that is, one with the same
  4902.              identity).  In the literature, this is referred to as two objects
  4903.              testing "isSame", or having the same "identity", or testing true
  4904.              for the "==" operator.  We will refer to this as two objects
  4905.              having the same identity.
  4906.  
  4907.  
  4908.  
  4909.           In C++, because of multiple inheritance, the address of a base class
  4910.           and its associated derived class may not be the same.  Because of
  4911.           this, if you compare two pointers (i.e., two addresses) to test for
  4912.           identity, the types of the two pointers should be the same.
  4913.  
  4914.  
  4915.           Smalltalk uses the operator "=" to test for equality, the operator
  4916.           "==" to test for identity.  However, in the C++ world, operator "="
  4917.           has become firmly attached to meaning assignment, operator "==" to
  4918.           generally meaning equality of values.  This is the approach we have
  4919.           taken.
  4920.  
  4921.  
  4922.  
  4923.  
  4924.  
  4925.  
  4926.                     
  4927.  
  4928.           6    The Rogue Wave collection classes allow a generalized
  4929.                test of equality -- it is up to you to define what it
  4930.                means for two objects to "be equal".  That is, a bit-by-
  4931.                bit comparison of the two objects is not done.  You could
  4932.                define "equality" to mean that a panda is the same as a
  4933.                deer because, in your context, they are both mammals.
  4934.  
  4935. Rogue WaveIntroduction To Collection Classes   81
  4936.  
  4937.  
  4938.  
  4939.  
  4940.  
  4941.  
  4942.  
  4943.  
  4944.                         USER'S GUIDE
  4945.  
  4946.  
  4947.  
  4948.           In the Rogue Wave Classes, the operator "==", when applied to two
  4949.           classes, generally means test for equality of values ("isEqual").  Of
  4950.           course, when applied to two pointers, it means test  for identity.
  4951.  
  4952.  
  4953.           Whether to test for equality or identity will depend on the context
  4954.           of your problem.  Here are some examples that might help.
  4955.  
  4956.           Suppose you were maintaining a mailing list.  Given a person's name,
  4957.           you want to find his or her address.  In this case, you would want to
  4958.           search for a name that is equal to the name at hand.  A Dictionary
  4959.           would be appropriate.  The key to the Dictionary would be the name,
  4960.           the value would be the address.
  4961.  
  4962.           Suppose you are writing a hypertext application.  You need to know in
  4963.           which document a particular graphic occurs.  This might be done by
  4964.           keeping a Dictionary of graphics and their corresponding document.
  4965.           In this case however, you would want an IdentityDictionary because
  4966.           you need to know in which document a particular graphic occurs.  The
  4967.           graphic acts as the key, the document as the value.
  4968.  
  4969.           Suppose you were maintaining a disk cache.  You might want to know
  4970.           whether a particular object is resident in memory.  In this case, an
  4971.           IdentitySet might be appropriate.  Given an object, you can check to
  4972.           see whether it exists in memory.
  4973.  
  4974.  
  4975.           13.1.1.2  Shallow versus deep copies
  4976.  
  4977.           There are two ways to make a copy of an object: shallow copying and
  4978.           deep copying.
  4979.  
  4980.           1. A shallow copy of an object is a new object whose instance
  4981.              variables are identical to the old object.  For example, a
  4982.              shallow copy of a Set will have the same members as the old set.
  4983.              The new Set will share objects with the old Set (through
  4984.              pointers).  Shallow copies are sometimes referred to as using
  4985.              reference semantics.
  4986.  
  4987.           2. A deep copy of an object will make a copy with entirely new
  4988.              instance variables.  The new object will not share objects with
  4989.              the old object.  For example, a deep copy of a Set would not only
  4990. Rogue WaveIntroduction To Collection Classes   82
  4991.  
  4992.  
  4993.  
  4994.  
  4995.  
  4996.  
  4997.  
  4998.  
  4999.                         USER'S GUIDE
  5000.  
  5001.              make a new set, but the items inserted into it would also be
  5002.              copies of the old items.  In a true deep copy, this copying is
  5003.              done recursively.  Deep copies are sometimes referred to as using
  5004.              value semantics.
  5005.  
  5006.  
  5007.  
  5008.           The copy constructors of most (but not all) Rogue Wave objects make
  5009.           shallow copies.  Some of the objects have a copy() member function
  5010.           that will return a new object with entirely new instance variables,
  5011.           although this copying is not done recursively (that is, the new
  5012.           instance variables are shallow copies of the old instance variables).
  5013.  
  5014.  
  5015.           Here's a graphical example.  Imagine a Bag (an unordered collection
  5016.           of objects with duplicates allowed) that looks like this before a
  5017.           copy :
  5018.  
  5019.  
  5020.  
  5021.  
  5022.  
  5023.           A shallow and deep copy of this collection would look like
  5024.           (respectively):
  5025.  
  5026.  
  5027.  
  5028.  
  5029.  
  5030.           Note that the deep copy not only made a copy of the bag itself, but
  5031.           also, recursively, any objects within it.
  5032.  
  5033.           Although shallow copies can be useful (and fast, because less copying
  5034.           is done), one must be careful because two collections now reference
  5035.           the same object.  If you delete all the items in one collection, you
  5036.           will leave the other collection pointing into nonsense.
  5037.  
  5038.           The issue of shallow versus deep copies can arise when an object is
  5039.           written to disk.  If an object includes two or more pointers or
  5040.           references to the same object, then when it is restored it is
  5041.           important that this morphology be preserved.  Classes which inherit
  5042.           from RWCollectable inherit a version of saveOn() which guarantees to
  5043.           preserve an object's morphology.  More on this later.
  5044.  
  5045. Rogue WaveIntroduction To Collection Classes   83
  5046.  
  5047.  
  5048.  
  5049.  
  5050.  
  5051.  
  5052.  
  5053.  
  5054.  
  5055.  
  5056.  
  5057.  
  5058.  
  5059.  
  5060.  
  5061.                                                           S e c t i o n    1 4 
  5062.  
  5063.  
  5064.                          "Generic" Collection ClassesCollection Classes generic
  5065.  
  5066.  
  5067.  
  5068.           This section describes the first general kind of collection classes
  5069.           included in the Tools.h++ Class Library: generic collection classes.
  5070.           They are so-called because they use the macros defined in
  5071.           <generic.h>, the current approximation to parameterized types in C++.
  5072.           For a review, see Stroustrup (1986, p. 209).  This is an area of
  5073.           rapid evolution of the C++ language -- in the future the language is
  5074.           likely to offer built-in parameterized types (see, for example,
  5075.           Lippman, 1989) and at that point Rogue Wave expects to support them.
  5076.           But, at the moment, the <generic.h> approach is all that we have.
  5077.           There is no reason to expect code built on it to become uncompilable
  5078.           in the future; presumably it would just be more unwieldy than
  5079.           whatever replaces it7.
  5080.  
  5081.           The general objective of the "generic" collection classes is to store
  5082.           and retrieve pointers to objects of a specified type.  However, there
  5083.           are two exceptions: class GVector(val) and class GSortedVector(val).
  5084.           In these classes, the type itself (which could be pointers to other
  5085.           objects) is stored.
  5086.  
  5087.           The storage and retrieval methods and criteria differ from class to
  5088.           class.  You are responsible for managing the objects themselves.
  5089.  
  5090.  
  5091.  
  5092.  
  5093.                     
  5094.  
  5095.           7    Actually, the generic macros are very easy to use, they
  5096.                are just difficult to write.  Because they are
  5097.                preprocessor macros, they must be "all on one line",
  5098.                making them very difficult to debug.
  5099.  
  5100. Rogue Wave   "Generic" Collection Classes   85
  5101.  
  5102.  
  5103.  
  5104.  
  5105.  
  5106.  
  5107.  
  5108.  
  5109.                         USER'S GUIDE
  5110.  
  5111.  
  5112. 14.1 Example
  5113.  
  5114.  
  5115.  
  5116.           Here is an example of using a GStack (generic stack) to store a set
  5117.           of pointers to ints in a last-in, first-out (LIFO) stack.  We will go
  5118.           through it line-by-line and explain what is happening:
  5119.  
  5120.             #include <gstack.h>                        //  1
  5121.             #include <rstream.h>                       //  2
  5122.  
  5123.             declare(GStack, int)                       //  3
  5124.  
  5125.             main()
  5126.             {
  5127.                GStack(int) gs;                         //  4
  5128.                gs.push(new int(1));                    //  5
  5129.                gs.push(new int(2));                    //  6
  5130.                gs.push(new int(3));                    //  7
  5131.                gs.push(new int(4));                    //  8
  5132.  
  5133.                cout << "Stack now has " << gs.entries() << " entries\n";   //
  5134.             9
  5135.  
  5136.                int* ip;                                // 10
  5137.                while( ip = gs.pop() )                  // 11
  5138.                  cout << *ip << "\n";                  // 12
  5139.             }
  5140.  
  5141.           Program output:
  5142.  
  5143.             Stack now has 4 entries
  5144.             4
  5145.             3
  5146.             2
  5147.             1
  5148.  
  5149.           Each program line is detailed below.
  5150.  
  5151.           1  This #include defines the preprocessor macro GStackdeclare(type).
  5152.              This macro is an elaborate and ugly looking thing that continues
  5153.              for many lines and describes how a "generic stack" of objects of
  5154.              type type should behave.  Mostly, it serves as a restricted
  5155. Rogue Wave   "Generic" Collection Classes   86
  5156.  
  5157.  
  5158.  
  5159.  
  5160.  
  5161.  
  5162.  
  5163.  
  5164.                         USER'S GUIDE
  5165.  
  5166.              interface to the underlying implementation, which is a singly-
  5167.              linked list (class RWSlist).  It is restricted because only
  5168.              certain member functions of RWSlist can be used (those
  5169.              appropriate to stacks) and because the items to be inserted into
  5170.              the stack must be of type type.
  5171.  
  5172.           2  <rstream.h> is a special Rogue Wave supplied header file that
  5173.              includes either the <iostream.h> (new, Release 2.0-compatible I/O
  5174.              streams) or <stream.h> (old, Release 1.2-compatible I/O streams)
  5175.              header file, depending on what is appropriate for your compiler.
  5176.              See Section 4.
  5177.  
  5178.           3  This line invokes the macro declare which is defined in the
  5179.              header file <generic.h>, supplied with your compiler.  If called
  5180.              with arguments declare(Class, type), it calls the macro
  5181.              Classdeclare with argument type.  Hence, in this case, the macro
  5182.              GStackdeclare  will be called (which was defined in <gstack.h>)
  5183.              with argument int.
  5184.  
  5185.  
  5186.  
  5187.           To summarize, the result of calling the declare(GStack, int) macro is
  5188.           that a new class has been created, especially for your program.  It
  5189.           will be a stack of pointers to ints.  Its name, for all practical
  5190.           purposes, is GStack(int).
  5191.  
  5192.  
  5193.           4  At this line an instance gs of the new class GStack(int) is
  5194.              created.
  5195.  
  5196.           5-8Four ints were created off the heap and inserted into the stack.
  5197.              After statement 8 executes, a pointer to the int "4" will be at
  5198.              the top of the stack, a pointer to the int "1" will be at the
  5199.              bottom.
  5200.  
  5201.           9  The member function entries() of class GStack(int) is called to
  5202.              verify how many items are on the stack.
  5203.  
  5204.           10 A pointer to an int is declared and defined.
  5205.  
  5206.           11 The stack is popped until empty.  The member function pop() will
  5207.              return and remove a pointer to the item on the top of the stack.
  5208.              If there are no more items on the stack it will return zero,
  5209.              causing the while loop to terminate.
  5210. Rogue Wave   "Generic" Collection Classes   87
  5211.  
  5212.  
  5213.  
  5214.  
  5215.  
  5216.  
  5217.  
  5218.  
  5219.                         USER'S GUIDE
  5220.  
  5221.           12 Each item is dereferenced and printed.
  5222.  
  5223.           Note that the macros have names starting with a capital "G".  This
  5224.           was chosen so that a generic name like "Stack" wouldn't accidentally
  5225.           get expanded by the <gstack.h> macros.
  5226.  
  5227.  
  5228. 14.2 Declaring generic collection classes
  5229.  
  5230.  
  5231.  
  5232.           All of the Tools.h++ generic collection classes are declared using
  5233.           the declare macro, defined in the header file <generic.h>, in a
  5234.           manner similar to the example above.  However, there is one important
  5235.           difference in how the Tools.h++ classes are declared versus the
  5236.           pattern set by Stroustrup (1986, Section 7.3.5).  This is summarized
  5237.           below:
  5238.  
  5239.             typedef int* intP;
  5240.             declare(GStack, intP)  // Wrong!
  5241.             declare(GStack, int)   // Correct.
  5242.  
  5243.           In Stroustrup, the class is declared using a typedef for a pointer to
  5244.           the collected item.  The Rogue Wave generic classes are declared
  5245.           using the item name itself.
  5246.  
  5247.           There are two exceptions to this rule: classes GVector(val) and
  5248.           GSortedVector(val) where a vector of items of type val will be
  5249.           created:
  5250.  
  5251.             declare(GVector,int)
  5252.  
  5253.             GVector(int) iv;
  5254.  
  5255.           The vector iv will be a vector of ints (rather than pointers to
  5256.           ints).
  5257.  
  5258.  
  5259. 14.3 User-defined functions
  5260.  
  5261.  
  5262.  
  5263.           Some of the member functions of the generic collection classes
  5264.           require a pointer to a user-defined function.  There are two kinds,
  5265. Rogue Wave   "Generic" Collection Classes   88
  5266.  
  5267.  
  5268.  
  5269.  
  5270.  
  5271.  
  5272.  
  5273.  
  5274.                         USER'S GUIDE
  5275.  
  5276.           discussed in the following two sections.
  5277.  
  5278.  
  5279. 14.3.1Tester functions
  5280.  
  5281.           The first kind of user-defined function is a "tester function".  It
  5282.           has the form:
  5283.  
  5284.             RWBoolean tester(const type* ty, const void* a)
  5285.  
  5286.           where tester is the name of the function, type is the type of the
  5287.           members of the collection class, and RWBoolean is a typedef for an
  5288.           int (whose only possible values are TRUE or FALSE).  The job of the
  5289.           tester function is to signal when a certain member of the collection
  5290.           has been identified.  The decision of how this is done, or what it
  5291.           means to have "identified" an object, is left to the user.  The user
  5292.           can chose to compare addresses (test for two objects being
  5293.           "identical"), or look for certain values within the object (test for
  5294.           "isEqual").  The first variable ty will point to a member of the
  5295.           collection and can be thought of as a "candidate".  The second
  5296.           variable a is available for your use to be tested against ty for a
  5297.           match.  It can be thought of as "client data", used to make the
  5298.           decision of whether there is a match.
  5299.  
  5300.           Here is an example that expands on the example in Section 14.1.  The
  5301.           problem is to push some values onto a stack and then to see if a
  5302.           certain value exists on the stack (test for "isEqual").
  5303.  
  5304.           The member function contains() of class GStack(type) has prototype:
  5305.  
  5306.             RWBoolean contains(    RWBoolean (*t)(const type*, const void*),
  5307.                             const void* a ) const;
  5308.  
  5309.           The first argument is RWBoolean (*t)(const type*, const void*).  This
  5310.           is a pointer to the tester function, for which we will have to
  5311.           provide an appropriate definition:
  5312.  
  5313.  
  5314.  
  5315.  
  5316.  
  5317.  
  5318.  
  5319.  
  5320. Rogue Wave   "Generic" Collection Classes   89
  5321.  
  5322.  
  5323.  
  5324.  
  5325.  
  5326.  
  5327.  
  5328.  
  5329.                         USER'S GUIDE
  5330.  
  5331.             #include <gstack.h>
  5332.             #include <rstream.h>
  5333.  
  5334.             declare(GStack, int)
  5335.  
  5336.             RWBoolean myTesterFunction(const int* jp, const void* a)  //  1
  5337.             {
  5338.                  return *jp == *(const int*)a;         //  2
  5339.             }
  5340.  
  5341.             main()
  5342.             {
  5343.                GStack(int) gs;                         //  3
  5344.                gs.push(new int(1));                    //  4
  5345.                gs.push(new int(2));                    //  5
  5346.                gs.push(new int(3));                    //  6
  5347.                gs.push(new int(4));                    //  7
  5348.  
  5349.                int aValue = 2;                         //  8
  5350.                if ( gs.contains(myTesterFunction, &aValue) )     //  9
  5351.                  cout << "Yup.\n";
  5352.                else
  5353.                  cout << "Nope.\n";
  5354.             }
  5355.  
  5356.           Program output:
  5357.  
  5358.             Yup.
  5359.  
  5360.           A description of each program line follows.
  5361.  
  5362.           1  This is the tester function.  Note that the first argument is a
  5363.              pointer to the type of objects in the collection, ints in this
  5364.              case.  The second argument points to an object that can be of any
  5365.              type.  In this example, it also points to an int.  Note that both
  5366.              arguments are declared const pointers -- in general the tester
  5367.              function should not change the value of the objects being pointed
  5368.              to.
  5369.  
  5370.           2  The second argument is converted from a const void* to a const
  5371.              int*, then dereferenced.  The result is a const int.  This is
  5372.              then compared to the dereferenced first argument, which is also a
  5373.              const int.  The net result is that this tester function considers
  5374.              a match to have occurred when the two ints have the same values
  5375. Rogue Wave   "Generic" Collection Classes   90
  5376.  
  5377.  
  5378.  
  5379.  
  5380.  
  5381.  
  5382.  
  5383.  
  5384.                         USER'S GUIDE
  5385.  
  5386.              (i.e., they are equal).  Note that we could have chosen to have
  5387.              identified a particular int (i.e., test for identity).
  5388.  
  5389.           3-7These lines are the same as in the example in Section 14.1.  A
  5390.              generic stack of (pointers to) ints is declared and defined, then
  5391.              4 values are pushed onto it.
  5392.  
  5393.           8  This is the value (i.e., "2") that we will look for in the stack.
  5394.  
  5395.           9  Here the member function contains() is called, using the tester
  5396.              function.  The second argument of contains() (a pointer to the
  5397.              variable aValue) will appear as the second argument of the tester
  5398.              function.  The function contains() traverses the entire stack,
  5399.              calling the tester function for each item in turn, waiting for
  5400.              the tester function to signal a match.  If it does, contains()
  5401.              returns TRUE, otherwise FALSE.
  5402.  
  5403.           Note that the second argument of the tester function does not
  5404.           necessarily have to be of the same type as the members of the
  5405.           collection (although it is in the example above).  Here is another
  5406.           example where they are not of the same type:
  5407.  
  5408.             #include <gstack.h>
  5409.             #include <rstream.h>
  5410.  
  5411.             class Foo {
  5412.             public:
  5413.                  int data;
  5414.                  Foo(int i) {data = i;}
  5415.             };
  5416.  
  5417.             declare(GStack, Foo)  // A stack of pointers to Foos
  5418.  
  5419.             RWBoolean anotherTesterFunction(const Foo* fp, const void* a)
  5420.             {
  5421.                  return fp->data == *(const int*)a;
  5422.             }
  5423.  
  5424.  
  5425.  
  5426.  
  5427.  
  5428.  
  5429.  
  5430. Rogue Wave   "Generic" Collection Classes   91
  5431.  
  5432.  
  5433.  
  5434.  
  5435.  
  5436.  
  5437.  
  5438.  
  5439.                         USER'S GUIDE
  5440.  
  5441.             main()
  5442.             {
  5443.                  GStack(Foo) gs;
  5444.                  gs.push(new Foo(1));
  5445.                  gs.push(new Foo(2));
  5446.                  gs.push(new Foo(3));
  5447.                  gs.push(new Foo(4));
  5448.  
  5449.                  int aValue = 2;
  5450.                  if ( gs.contains(anotherTesterFunction, &aValue) )
  5451.                     cout << "Yup.\n";
  5452.                  else
  5453.                     cout << "Nope.\n";
  5454.             }
  5455.  
  5456.           Here, a stack of (pointers to) Foos is declared and used, while the
  5457.           variable being passed as the second argument to the tester function
  5458.           is still a const int*.  The tester function must take this into
  5459.           account.
  5460.  
  5461.  
  5462. 14.3.2Apply functions
  5463.  
  5464.           The second kind of user-defined function is an "apply function".  Its
  5465.           general form is:
  5466.  
  5467.             void yourApplyFunction(type* ty, void* a)
  5468.  
  5469.           where yourApplyFunction is the name of the function and type is the
  5470.           type of the members of the collection.  Apply functions give you the
  5471.           opportunity to perform some operation on each member of a collection
  5472.           (perhaps print it out or draw it on a screen).  The second argument
  5473.           is designed to hold "client data" to be used by the function (perhaps
  5474.           the handle of a window on which the object is to be drawn).
  5475.  
  5476.  
  5477.  
  5478.  
  5479.  
  5480.  
  5481.  
  5482.  
  5483.  
  5484.  
  5485. Rogue Wave   "Generic" Collection Classes   92
  5486.  
  5487.  
  5488.  
  5489.  
  5490.  
  5491.  
  5492.  
  5493.  
  5494.                         USER'S GUIDE
  5495.  
  5496.           Here is an example, using class GDlist(type) -- a generic doubly-
  5497.           linked list:
  5498.  
  5499.             #include <gdlist.h>
  5500.             #include <rstream.h>
  5501.  
  5502.             class Foo {
  5503.             public:
  5504.                  int val;
  5505.                  Foo(int i) {val = i;}
  5506.             };
  5507.  
  5508.             declare(GDlist, Foo)
  5509.  
  5510.             void printAFoo(Foo* ty, void* sp)
  5511.             {
  5512.                  ostream* s = (ostream*)sp;
  5513.                  (*s) << ty->val << "\n";
  5514.             }
  5515.  
  5516.             main()
  5517.             {
  5518.                  GDlist(Foo) gd;
  5519.                  gd.append(new Foo(1));
  5520.                  gd.append(new Foo(2));
  5521.                  gd.append(new Foo(3));
  5522.                  gd.append(new Foo(4));
  5523.  
  5524.                  gd.apply(printAFoo, &cout);
  5525.             }
  5526.  
  5527.           Program output:
  5528.  
  5529.             1
  5530.             2
  5531.             3
  5532.             4
  5533.  
  5534.           The items are appended at the tail of the list (see Part II: Class
  5535.           Reference).  For each item, the apply() function calls the user-
  5536.           defined function printAFoo() with the address of the item as the
  5537.           first argument and the address of an ostream (an output stream) as
  5538.           the second argument.  The job of printAFoo() is to print out the
  5539.           value of member data val.  Because apply() scans the list from
  5540. Rogue Wave   "Generic" Collection Classes   93
  5541.  
  5542.  
  5543.  
  5544.  
  5545.  
  5546.  
  5547.  
  5548.  
  5549.                         USER'S GUIDE
  5550.  
  5551.           beginning to end, the items will come out in the same order in which
  5552.           they were inserted.
  5553.  
  5554.           With some care, apply functions can be used to change the objects in
  5555.           a collection.  For example, you could use an apply function to change
  5556.           the value of member data val in the example above, or to delete all
  5557.           member objects.  But, in the latter case, you must be careful not to
  5558.           use the collection again.
  5559.  
  5560.  
  5561.  
  5562.  
  5563.  
  5564.  
  5565.  
  5566.  
  5567.  
  5568.  
  5569.  
  5570.  
  5571.  
  5572.  
  5573.  
  5574.  
  5575.  
  5576.  
  5577.  
  5578.  
  5579.  
  5580.  
  5581.  
  5582.  
  5583.  
  5584.  
  5585.  
  5586.  
  5587.  
  5588.  
  5589.  
  5590.  
  5591.  
  5592.  
  5593.  
  5594.  
  5595. Rogue Wave   "Generic" Collection Classes   94
  5596.  
  5597.  
  5598.  
  5599.  
  5600.  
  5601.  
  5602.  
  5603.  
  5604.  
  5605.  
  5606.  
  5607.  
  5608.  
  5609.  
  5610.  
  5611.                                                           S e c t i o n    1 5 
  5612.  
  5613.  
  5614.  
  5615.  
  5616.             Smalltalk -like Collection ClassesCollection Classes Smalltalk-like
  5617.  
  5618.  
  5619.  
  5620.  
  5621. 15.1 Introduction
  5622.  
  5623.  
  5624.  
  5625.           The second general type of collection classes provided with the
  5626.           Tools.h++ Class Library is a set of "Smalltalk-80-like Collection
  5627.           Classes".  In this approach, objects to be collected must inherit the
  5628.           abstract base class "RWCollectable" using either single or  multiple
  5629.           inheritance.  The principal advantage of this approach is that the
  5630.           programming-interface is much cleaner and the collection classes are
  5631.           far more powerful.  The disadvantage is that the objects are slightly
  5632.           larger and the collection classes are slightly slower.
  5633.  
  5634.           Many of these classes have a typedef to either the corresponding
  5635.           Smalltalk names, or to a generic name.  Table 15-1 summarizes.
  5636.  
  5637.  
  5638.  
  5639.  Class               Iterator               "Smalltalk"    Implemented as
  5640.                                             typedef
  5641.  
  5642.  
  5643.  RWBag               RWBagIterator          Bag      Dictionary of occurrences
  5644.  
  5645.  RWBinaryTree        RWBinaryTree-Iterator  SortedCollection       Binary tree
  5646.  
  5647.  RWBTree                                                   B-Tree in memory
  5648.  
  5649.  
  5650. Rogue Wave Smaltalk_-like Collection Classes   95
  5651.  
  5652.  
  5653.  
  5654.  
  5655.  
  5656.  
  5657.  
  5658.  
  5659.                         USER'S GUIDE
  5660.  
  5661.  RWBTreeDictionary                                      B-Tree of associations
  5662.  
  5663.  RWCollection        RWIterator             Collection     Abstract base class
  5664.  
  5665.  
  5666.  
  5667. Table 15-1.    Smalltalk-like collection classes, their iterators and
  5668.           implementations.
  5669.                                                           (continued next page)
  5670.  
  5671.  
  5672.  
  5673.  
  5674.  
  5675.  
  5676.  
  5677.  
  5678.  
  5679.  
  5680.  
  5681.  
  5682.  
  5683.  
  5684.  
  5685.  
  5686.  
  5687.  
  5688.  
  5689.  
  5690.  
  5691.  
  5692.  
  5693.  
  5694.  
  5695.  
  5696.  
  5697.  
  5698.  
  5699.  
  5700.  
  5701.  
  5702.  
  5703.  
  5704.  
  5705. Rogue WaveSmalltalk_-like Collection Classes   96
  5706.  
  5707.  
  5708.  
  5709.  
  5710.  
  5711.  
  5712.  
  5713.  
  5714.                         USER'S GUIDE
  5715.  
  5716.           Table 15-1. continued
  5717.  
  5718.  
  5719.  
  5720.  Class                Iterator             "Smalltalk"    Implemented as
  5721.                                            typedef
  5722.  
  5723.  
  5724.  RWDlistCollectables  RWDlistCollectables                 Doubly-linked list
  5725.  
  5726.                       Iterator
  5727.  
  5728.  RWHashDictionary     RWHashDictionary-    Dictionary     Hash table of
  5729.  
  5730.                       Iterator                            associations
  5731.  
  5732.  RWIdentity           RWHashDictionary-    Identity       Hash table of
  5733.  
  5734.  Dictionary           Iterator             Dictionary     associations
  5735.  
  5736.  RWIdentitySet        RWSetIterator        IdentitySet    Hash table
  5737.  
  5738.  RWOrdered            RWOrderedIterator    Ordered        Vector of pointers
  5739.  
  5740.                                            Collection
  5741.  
  5742.  RWSequenceable       RWIterator           Sequenceable   Abstract base class
  5743.  
  5744.  RWSet                RWSetIterator        Set            Hash table
  5745.  
  5746.  RWSlist              RWSlistCollectables- LinkedList     Singly-linked list
  5747.  
  5748.  Collectables         Iterator
  5749.  
  5750.  RWSlist              (n/a)                Queue          Singly-linked list
  5751.  
  5752.  CollectablesQueue
  5753.  
  5754.  RWSlist              (n/a)                Stack          Singly-linked list
  5755.  
  5756.  CollectablesStack
  5757.  
  5758.  
  5759.  
  5760. Rogue WaveSmalltalk_-like Collection Classes   97
  5761.  
  5762.  
  5763.  
  5764.  
  5765.  
  5766.  
  5767.  
  5768.  
  5769.                         USER'S GUIDE
  5770.  
  5771.  RWSortedVector       RWSortedVector-                     Vector of pointers,
  5772.  
  5773.                       Iterator                            using insertion sort
  5774.  
  5775.  
  5776.  
  5777.  
  5778.  
  5779.  
  5780.  
  5781.  
  5782.  
  5783.  
  5784.  
  5785.  
  5786.  
  5787.  
  5788.  
  5789.  
  5790.  
  5791.  
  5792.  
  5793.  
  5794.  
  5795.  
  5796.  
  5797.  
  5798.  
  5799.  
  5800.  
  5801.  
  5802.  
  5803.  
  5804.  
  5805.  
  5806.  
  5807.  
  5808.  
  5809.  
  5810.  
  5811.  
  5812.  
  5813.  
  5814.  
  5815. Rogue WaveSmalltalk_-like Collection Classes   98
  5816.  
  5817.  
  5818.  
  5819.  
  5820.  
  5821.  
  5822.  
  5823.  
  5824.                         USER'S GUIDE
  5825.  
  5826.  
  5827.  
  5828.  
  5829.           RWCollectable
  5830.  
  5831.             RWCollection (abstract base class)
  5832.  
  5833.                RWBinaryTree
  5834.  
  5835.                RWBTree
  5836.  
  5837.                  RWBTreeDictionary
  5838.  
  5839.                RWBag
  5840.  
  5841.                RWSequenceable (abstract base class)
  5842.  
  5843.                  RWDlistCollectables (Doubly-linked lists)
  5844.  
  5845.                  RWOrdered
  5846.  
  5847.                     RWSortedVector
  5848.  
  5849.                  RWSlistCollectables (Singly-linked lists)
  5850.  
  5851.                     RWSlistCollectablesQueue
  5852.  
  5853.                     RWSlistCollectablesStack
  5854.  
  5855.                RWSet
  5856.  
  5857.                  RWIdentitySet
  5858.  
  5859.                  RWHashDictionary
  5860.  
  5861.                     RWIdentityDictionary
  5862.  
  5863.  
  5864.  
  5865.  
  5866.  
  5867. Table 15-2.    The class hierarchy of the Smalltalk_-like collection classes.
  5868.           Note that some of these classes use multiple-inheritance: this
  5869.           hierarchy is shown relative to the RWCollectable base class.
  5870. Rogue WaveSmalltalk_-like Collection Classes   99
  5871.  
  5872.  
  5873.  
  5874.  
  5875.  
  5876.  
  5877.  
  5878.  
  5879.                         USER'S GUIDE
  5880.  
  5881.  
  5882.  
  5883.  
  5884.  
  5885.  
  5886.  
  5887.  
  5888.  
  5889.  
  5890.  
  5891.  
  5892.  
  5893.  
  5894.  
  5895.  
  5896.  
  5897.  
  5898.  
  5899.  
  5900.  
  5901.  
  5902.  
  5903.  
  5904.  
  5905.  
  5906.  
  5907.  
  5908.  
  5909.  
  5910.  
  5911.  
  5912.  
  5913.  
  5914.  
  5915.  
  5916.  
  5917.  
  5918.  
  5919.  
  5920.  
  5921.  
  5922.  
  5923.  
  5924.  
  5925. Rogue WaveSmalltalk_-like Collection Classes   100
  5926.  
  5927.  
  5928.  
  5929.  
  5930.  
  5931.  
  5932.  
  5933.  
  5934.                         USER'S GUIDE
  5935.  
  5936.  
  5937. 15.2 Example
  5938.  
  5939.  
  5940.  
  5941.           To get us oriented, it is always good to look at an example.  This
  5942.           code uses a SortedCollection to store and order a set of
  5943.           RWCollectableStrings.  We will go through it line-by-line and explain
  5944.           what is happening:
  5945.  
  5946.             #include <bintree.h>                       //  1
  5947.             #include <collstr.h>                       //  2
  5948.             #include <rstream.h>
  5949.  
  5950.             main()
  5951.             {
  5952.  
  5953.                // Construct an empty SortedCollection
  5954.                SortedCollection sc;                    //  3
  5955.  
  5956.                // Insert some RWCollectableStrings:
  5957.                sc.insert(new RWCollectableString("George"));     //  4
  5958.                sc.insert(new RWCollectableString("Mary"));//  5
  5959.                sc.insert(new RWCollectableString("Bill"));//  6
  5960.                sc.insert(new RWCollectableString("Throkmorton"));     //  7
  5961.  
  5962.                // Now iterate through the collection, printing all members:
  5963.                RWCollectableString* str;               //  8
  5964.                RWSortedCollectionIterator sci(sc);     //  9
  5965.                while( str = (RWCollectableString*)sci() )// 10
  5966.                  cout << *str << NL;                   // 11
  5967.             }
  5968.  
  5969.           Program output:
  5970.  
  5971.             Bill
  5972.             George
  5973.             Mary
  5974.             Throkmorton
  5975.  
  5976.           SortedCollection is actually a typedef for a RWBinaryTree.  Objects
  5977.           inserted into it are stored in order according to relative values
  5978.           returned by the virtual function compareTo() (see Section 15.10.5).
  5979.  
  5980. Rogue WaveSmalltalk_-like Collection Classes   101
  5981.  
  5982.  
  5983.  
  5984.  
  5985.  
  5986.  
  5987.  
  5988.  
  5989.                         USER'S GUIDE
  5990.  
  5991.           1  This first #include statement declares the class RWBinaryTree,
  5992.              the true identity of a SortedCollection.
  5993.  
  5994.           2  The second #include declares class RWCollectableString which is a
  5995.              derived class with classes RWString and RWCollectable as base
  5996.              classes.  Multiple inheritance was used to create this class.
  5997.              Most of its functionality is inherited from class RWString.  Its
  5998.              ability to be "collected" was inherited from class RWCollectable.
  5999.  
  6000.           3  An empty SortedCollection was created at this line.
  6001.  
  6002.           4-7Four RWCollectableStrings were created off the heap and inserted
  6003.              into the collection.  See Part II: Class Reference for details on
  6004.              constructors for RWCollectableStrings.  The insertions were not
  6005.              done in any particular order.
  6006.  
  6007.           8  A pointer to a RWCollectableString was declared and defined here.
  6008.  
  6009.           9  An iterator was constructed from the SortedCollection sc.
  6010.  
  6011.           10 The iterator is then used to step through the entire collection,
  6012.              retrieving each value in order.  The function call operator
  6013.              (i.e., operator()) has been overloaded for the iterator to mean
  6014.              "step to the next item and return a pointer to it".  All
  6015.              Tools.h++ iterators work this way.  See Stroustrup (1986, Section
  6016.              7.3.2) for an example and discussion of iterators, as well as
  6017.              Section 15.6 of this manual.  The typecast
  6018.  
  6019.                     str = (RWCollectableString*)sci()
  6020.  
  6021.              is necessary because the iterator returns a RWCollectable* (that
  6022.              is, a pointer to a RWCollectable) which must then be cast into
  6023.              its actual identity.
  6024.  
  6025.           11 Finally, the pointer str is dereferenced and printed.  The
  6026.              ability of a RWCollectableString to be printed is inherited from
  6027.              its base class RWString.  The macro NL will print a newline,
  6028.              irregardless of the type of streams your compiler supports.  See
  6029.              Section 4.
  6030.  
  6031.           When run, the program prints out the four collected strings "in
  6032.           order".  For class RWCollectableString, this means in lexicographical
  6033.           order.
  6034.  
  6035. Rogue WaveSmalltalk_-like Collection Classes   102
  6036.  
  6037.  
  6038.  
  6039.  
  6040.  
  6041.  
  6042.  
  6043.  
  6044.                         USER'S GUIDE
  6045.  
  6046.  
  6047. 15.3 Virtual functions inherited from RWCollection
  6048.  
  6049.  
  6050.  
  6051.           The Smalltalk_-like collection classes inherited from the abstract
  6052.           base class RWCollection which, in turn, inherits from the abstract
  6053.           base class RWCollectable, described below (making it is possible to
  6054.           have collections of collections).
  6055.  
  6056.           An "abstract base class" is a class that is not intended to be used
  6057.           per se, but rather to be inherited by some other class.  Its virtual
  6058.           functions provide a template of functionality that act as a surrogate
  6059.           for the derived class.  The class RWCollection is such a class.  It
  6060.           provides a template for "collection" classes by declaring various
  6061.           virtual functions such as insert(), remove(), entries(), etc.
  6062.  
  6063.           This section describes the virtual functions inherited by all of the
  6064.           Smalltalk-like collections.  Any collection can be expected to
  6065.           understand them.
  6066.  
  6067.  
  6068. 15.3.1insert()
  6069.  
  6070.             virtual RWCollectable* insert(RWCollectable*);
  6071.  
  6072.           A pointer to an object is put into a collection by using insert().
  6073.           It inserts in the "most natural way" for the collection.  For a
  6074.           stack, this means it is pushed onto the stack.  For a queue, the item
  6075.           is appended to the queue.  For a sorted collection, the item is
  6076.           inserted such that items before it compare less than (or equal to if
  6077.           duplicates are allowed) itself, items after it compare greater than
  6078.           itself.  See the example in Section 15.2 for an example of insert().
  6079.  
  6080.  
  6081. 15.3.2find() and friends
  6082.  
  6083.             virtual RWBoolean      contains(const RWCollectable*) const;
  6084.             virtual unsigned       entries() const;
  6085.             virtual RWCollectable* find(const RWCollectable*) const;
  6086.             virtual RWBoolean      isEmpty() const;
  6087.             virtual unsigned       occurrencesOf(const RWCollectable*) const;
  6088.  
  6089.           These functions test how many objects the collection contains and
  6090. Rogue WaveSmalltalk_-like Collection Classes   103
  6091.  
  6092.  
  6093.  
  6094.  
  6095.  
  6096.  
  6097.  
  6098.  
  6099.                         USER'S GUIDE
  6100.  
  6101.           whether it contains a particular object.  The function isEmpty()
  6102.           returns true if the collection contains no objects.  The function
  6103.           entries() returns the total number of objects that the collection
  6104.           contains.
  6105.  
  6106.           The function contains() returns TRUE if the argument is equal to an
  6107.           item within the collection.  The meaning of "is equal to" depends on
  6108.           the collection and the type of object being tested.  Hashing
  6109.           collections use the virtual function isEqual() to test for equality
  6110.           (with the hash() function used to narrow the choices).  Sorted
  6111.           collections search for an item that "compares equal" (i.e.
  6112.           compareTo() returns zero) to the argument.
  6113.  
  6114.           The virtual function occurrencesOf() is similar to contains(), but
  6115.           returns the number of items that are equal to the argument.
  6116.  
  6117.           The virtual function find() returns a pointer to an item that is
  6118.           equal to its argument.
  6119.  
  6120.           Here is an example that builds on the example in Section 15.2 and
  6121.           uses some of these functions:
  6122.  
  6123.             #include <bintree.h>                       //  1
  6124.             #include <collstr.h>                       //  2
  6125.             #include <rstream.h>
  6126.  
  6127.             main()
  6128.             {
  6129.  
  6130.                // Construct an empty SortedCollection
  6131.                SortedCollection sc;                    //  3
  6132.  
  6133.                // Insert some RWCollectableStrings:
  6134.                sc.insert(new RWCollectableString("George"));     //  4
  6135.                sc.insert(new RWCollectableString("Mary"));//  5
  6136.                sc.insert(new RWCollectableString("Bill"));//  6
  6137.                sc.insert(new RWCollectableString("Throkmorton"));     //  7
  6138.                sc.insert(new RWCollectableString("Mary"));//  8
  6139.  
  6140.                cout << sc.entries() << "\n";           //  9
  6141.  
  6142.                RWCollectableString dummy("Mary");      // 10
  6143.                RWCollectable* t = sc.find( &dummy );   // 11
  6144.  
  6145. Rogue WaveSmalltalk_-like Collection Classes   104
  6146.  
  6147.  
  6148.  
  6149.  
  6150.  
  6151.  
  6152.  
  6153.  
  6154.                         USER'S GUIDE
  6155.  
  6156.                if(t){                                  // 12
  6157.                  if(t->isA() == dummy.isA())           // 13
  6158.                     cout << *(RWCollectableString*)t << "\n";    // 14
  6159.                }
  6160.                else
  6161.                  cout << "Object not found.\n";        // 15
  6162.  
  6163.                cout << sc.occurrencesOf(&dummy) << "\n";// 16
  6164.  
  6165.           Program output:
  6166.  
  6167.             5
  6168.             Mary
  6169.             2
  6170.  
  6171.           Here's the line-by-line description:
  6172.  
  6173.           1-7These lines are as in Section 15.2.
  6174.  
  6175.           8  Insert another instance with the value "Mary".
  6176.  
  6177.           9  This statement prints out the total number of entries in the
  6178.              sorted collection: 5.
  6179.  
  6180.           10 A throwaway variable "dummy" is constructed, to be used to test
  6181.              for the occurrences of strings containing "Mary".
  6182.  
  6183.           11 The collection is asked to return a pointer to the first object
  6184.              encountered that compares equal to the argument.  A nil pointer
  6185.              (zero) is returned if there is no such object.
  6186.  
  6187.           12 The pointer is tested to make sure it is not nil.
  6188.  
  6189.           13 Paranoid check.  In this example, it is obvious that the items in
  6190.              the collection must be of type RWCollectableString.  In general,
  6191.              it may not be obvious.
  6192.  
  6193.           14 Because of the results of step 13, the cast to a
  6194.              RWCollectableString pointer is safe.  The pointer is then
  6195.              dereferenced and printed.
  6196.  
  6197.           15 If the pointer t was nil, then an error message would have been
  6198.              printed here.
  6199.  
  6200. Rogue WaveSmalltalk_-like Collection Classes   105
  6201.  
  6202.  
  6203.  
  6204.  
  6205.  
  6206.  
  6207.  
  6208.  
  6209.                         USER'S GUIDE
  6210.  
  6211.           16 The call to occurrencesOf() returns the number of items that
  6212.              compare equal to its argument.  In this case, two items are found
  6213.              (the two occurrences of "Mary").
  6214.  
  6215.  
  6216. 15.3.3remove() functions
  6217.  
  6218.             virtual RWCollectable* remove(const RWCollectable*);
  6219.             virtual void      removeAndDestroy(const RWCollectable*);
  6220.  
  6221.           The function remove() looks for an item that is equal to its argument
  6222.           and removes it from the collection, returning a pointer to it.  It
  6223.           returns nil if no item was found.
  6224.  
  6225.           The function removeAndDestroy() is similar except that rather than
  6226.           return the item, it deletes it, using the virtual destructor
  6227.           inherited by all RWCollectable items.  You must be careful when using
  6228.           this function that the item was actually allocated off the heap (i.e.
  6229.           not the stack) and that it is not shared with another collection.
  6230.  
  6231.           Expanding on the example above:
  6232.  
  6233.                  RWCollectable* oust = sc.remove(&dummy);// 17
  6234.                  delete oust;                          // 18
  6235.  
  6236.                  sc.removeAndDestroy(&dummy);          // 19
  6237.  
  6238.           17 Removes the first occurrence of the string containing "Mary" and
  6239.              returns a pointer to it.  This pointer will be nil if there was
  6240.              no such item.
  6241.  
  6242.           18 Delete the item (which was originally allocated off the heap).
  6243.              There is no need to check the pointer against nil because the
  6244.              language guarantees that it is always OK to delete a nil
  6245.              pointer8.
  6246.  
  6247.           19 In this statement, the remaining occurrence of "Mary" is not only
  6248.              removed, but also deleted.
  6249.                     
  6250.  
  6251.           8    Actually, at the time of this writing, the Zortech V2.06
  6252.                through V2.18 compilers will abort if an attempt is made
  6253.                to delete a nil pointer.
  6254.  
  6255. Rogue WaveSmalltalk_-like Collection Classes   106
  6256.  
  6257.  
  6258.  
  6259.  
  6260.  
  6261.  
  6262.  
  6263.  
  6264.                         USER'S GUIDE
  6265.  
  6266.  
  6267. 15.3.4apply() functions
  6268.  
  6269.             virtual void apply(RWapplyCollectable ap, void* x);
  6270.  
  6271.           An efficient method for examining the members of a Smalltalk-like
  6272.           collection is member function apply().  The first argument
  6273.           (RWapplyCollectable) is a typedef:
  6274.  
  6275.             typedef void (*RWapplyCollectable)(RWCollectable*, void*);
  6276.  
  6277.           that is, a pointer to a function with prototype:
  6278.  
  6279.             void yourApplyFunction(RWCollectable* item, void* x)
  6280.  
  6281.           where yourApplyFunction is the name of the function.  You must supply
  6282.           this function.  It will be called for each item in the collection, in
  6283.           whatever order is appropriate for the collection, and passed a
  6284.           pointer to the item as its first argument.  The second argument (x)
  6285.           is passed through from the call to apply() and is available for your
  6286.           use.  It could be used, for example, to hold a handle to a window on
  6287.           which the object is to be drawn, etc.
  6288.  
  6289.           Note the similarity to the apply() function of the generic collection
  6290.           classes (Section 14.3.2).  The difference is in the type of the first
  6291.           argument of the user-supplied function (RWCollectable* rather than
  6292.           type*).  As with the generic classes, you must be careful that you
  6293.           cast the pointer item to the proper derived class.
  6294.  
  6295.           The apply functions generally employ the "most efficient method" for
  6296.           examining all members of the collection.  This is their great
  6297.           advantage.  Their disadvantage is that they are slightly clumsy to
  6298.           use, requiring the user to supply a separate function9.
  6299.  
  6300.  
  6301.                     
  6302.  
  6303.           9    The functional equivalent to apply() in the Smalltalk
  6304.                world is "do".  It takes just one argument -- a piece of
  6305.                code to be evaluated for each item in the collection.
  6306.                This keeps the method and the block to be evaluated
  6307.                together in one place, resulting in cleaner code.  As
  6308.                usual, the C++ approach is messier.
  6309.  
  6310. Rogue WaveSmalltalk_-like Collection Classes   107
  6311.  
  6312.  
  6313.  
  6314.  
  6315.  
  6316.  
  6317.  
  6318.  
  6319.                         USER'S GUIDE
  6320.  
  6321.  
  6322. 15.3.5Functions clear() and clearAndDestroy()
  6323.  
  6324.             virtual void clear();
  6325.             virtual void clearAndDestroy();
  6326.  
  6327.           The function clear() removes all items from the collection.
  6328.  
  6329.           The function clearAndDestroy() not only removes the items, but also
  6330.           calls the virtual destructor for each item.  Although it does check
  6331.           to see if the same item occurs more than once in a collection (by
  6332.           building an IdentitySet internally) and thereby deletes each item
  6333.           only once, it must still be used with care.  It cannot check to see
  6334.           whether an item is shared between two different collections.  You
  6335.           must also be certain that all possible members of the collection were
  6336.           allocated off the heap.
  6337.  
  6338.  
  6339. 15.4 Other functions shared by all RWCollections
  6340.  
  6341.  
  6342.  
  6343.           There are several other functions that are shared by all classes that
  6344.           inherit from RWCollection.  Note that these are not virtual
  6345.           functions.
  6346.  
  6347.  
  6348. 15.4.1Class conversions
  6349.  
  6350.             RWBag             asBag() const;
  6351.             RWSet             asSet() const;
  6352.             RWOrdered         asOrderedCollection() const;
  6353.             RWBinaryTree asSortedCollection() const
  6354.  
  6355.           These functions allow any collection class to be converted into a
  6356.           RWBag, RWSet, RWOrdered, or a SortedCollection (i.e., a
  6357.           RWBinaryTree).
  6358.  
  6359.  
  6360. 15.4.2Inserting and removing other collections
  6361.  
  6362.             void operator+=(const RWCollection&);
  6363.             void operator-=(const RWCollection&);
  6364.  
  6365. Rogue WaveSmalltalk_-like Collection Classes   108
  6366.  
  6367.  
  6368.  
  6369.  
  6370.  
  6371.  
  6372.  
  6373.  
  6374.                         USER'S GUIDE
  6375.  
  6376.           These functions insert or remove (respectively) the contents of their
  6377.           argument.
  6378.  
  6379.  
  6380. 15.4.3Selection
  6381.  
  6382.             typedef RWBoolean
  6383.                  (*testCollectable)(const RWCollectable*, const void*);
  6384.  
  6385.             RWCollection*     select(testCollectable tst, void*);
  6386.  
  6387.           The function select() evaluates the function pointed to by tst for
  6388.           each item in the collection.  It inserts those items for which the
  6389.           function returns TRUE into a new collection of the same type as self
  6390.           and returns a pointer to it.  This new collection is allocated off
  6391.           the heap, hence you are responsible for deleting it when done.
  6392.  
  6393.  
  6394. 15.5 Virtual functions inherited from RWSequenceable
  6395.  
  6396.  
  6397.  
  6398.           The abstract base class RWSequenceable is derived from RWCollection.
  6399.           Collections that inherit from it have an inate ordering.  That is,
  6400.           the ordering is meaningful (unlike, say, a hash table).
  6401.  
  6402.             virtual RWCollectable*&          at(int i);
  6403.             virtual const RWCollectable*     at(int i) const;
  6404.  
  6405.           These virtual functions allow access to the i'th item in the
  6406.           collection, similar to subscripting an array.  The compiler choses
  6407.           which function to use on the basis of whether or not your collection
  6408.           has been declared "const".  If it has, the second variant is used,
  6409.           otherwise the first.  The first can be used as an lvalue:
  6410.  
  6411.             RWOrdered od;
  6412.             od.insert(new RWCollectableInt(0));   // 0
  6413.             od.insert(new RWCollectableInt(1));   // 0 1
  6414.             od.insert(new RWCollectableInt(2));   // 0 1 2
  6415.  
  6416.             delete od(1);     // Use variant available for RWOrdered
  6417.             od.at(1) = new RWCollectableInt(3);   // 0 3 2
  6418.  
  6419.           These operation are very efficient for the class RWOrdered (which is
  6420. Rogue WaveSmalltalk_-like Collection Classes   109
  6421.  
  6422.  
  6423.  
  6424.  
  6425.  
  6426.  
  6427.  
  6428.  
  6429.                         USER'S GUIDE
  6430.  
  6431.           implemented as a vector) but, as you might expect, relatively
  6432.           inefficient for classes implemented as a linked-list (the entire list
  6433.           must be traversed in order to find a particular index).
  6434.  
  6435.             virtual RWCollectable* first() const;
  6436.             virtual RWCollectable* last() const;
  6437.  
  6438.           These functions return the first or last item in the collection,
  6439.           respectively, or nil if the collection is empty.
  6440.  
  6441.             virtual int  index(const RWCollectable*) const;
  6442.  
  6443.  
  6444.  
  6445.  
  6446.  
  6447.  
  6448.  
  6449.  
  6450.  
  6451.  
  6452.  
  6453.  
  6454.  
  6455.  
  6456.  
  6457.  
  6458.  
  6459.  
  6460.  
  6461.  
  6462.  
  6463.  
  6464.  
  6465.  
  6466.  
  6467.  
  6468.  
  6469.  
  6470.  
  6471.  
  6472.  
  6473.  
  6474.  
  6475. Rogue WaveSmalltalk_-like Collection Classes   110
  6476.  
  6477.  
  6478.  
  6479.  
  6480.  
  6481.  
  6482.  
  6483.  
  6484.                         USER'S GUIDE
  6485.  
  6486.           This function returns the index of the first object that is equal to
  6487.           the argument:
  6488.  
  6489.             RWOrdered od;
  6490.             od.insert(new RWCollectableInt(6));   // 6
  6491.             od.insert(new RWCollectableInt(2));   // 6 2
  6492.             od.insert(new RWCollectableInt(4));   // 6 2 4
  6493.  
  6494.             RWCollectableInt dummy(2);
  6495.             cout << od.index(&dummy) << "\n";
  6496.  
  6497.           Program output:
  6498.  
  6499.             1
  6500.  
  6501.             virtual RWCollectable* insertAfter(int, RWCollectable*);
  6502.  
  6503.           This function inserts its second argument after the item at the index
  6504.           of the first argument.
  6505.  
  6506.             RWOrdered od;
  6507.             od.insert(new RWCollectableInt(6));        // 6
  6508.             od.insert(new RWCollectableInt(2));        // 6 2
  6509.             od.insertAfter(0, new RWCollectableInt(4));     // 6 4 2
  6510.  
  6511. 15.6 Iterators
  6512.  
  6513.  
  6514.  
  6515.           An iterator is an alternative method to the apply() function for
  6516.           visiting all of the items in a collection.  We saw an example of one
  6517.           in action in Section 15.2.  The advantage of an iterator is that it
  6518.           maintains an internal state, allowing two important benefits:  more
  6519.           than one iterator can be constructed from the same collection, and
  6520.           all of the items need not be visited in a single sweep.
  6521.  
  6522.           Iterators are always constructed from the collection itself.  For
  6523.           example:
  6524.  
  6525.             SortedCollection sc;
  6526.             .
  6527.             .
  6528.             .
  6529.             SortedCollectionIterator sci(sc);
  6530. Rogue WaveSmalltalk_-like Collection Classes   111
  6531.  
  6532.  
  6533.  
  6534.  
  6535.  
  6536.  
  6537.  
  6538.  
  6539.                         USER'S GUIDE
  6540.  
  6541.  
  6542.           If you change the collection by adding or deleting objects while an
  6543.           iterator is active, the state of the iterator becomes undefined --
  6544.           using it could bring unpredictable results.  The member function
  6545.           reset() will bring it back to its senses.
  6546.  
  6547.           At any given moment the iterator "marks" an object in the collection.
  6548.           You can think of it as the "current" object.  There are various
  6549.           methods for moving this "mark".
  6550.  
  6551.           Most of the time you will probably be using member function
  6552.           operator().  It is designed to always advance to the next object,
  6553.           then return it.  It always returns nil (i.e., zero) when the end of
  6554.           the collection is reached.
  6555.  
  6556.           Some iterators have other member functions for manipulating the mark,
  6557.           such as findNext() or removeNext().
  6558.  
  6559.           Member function key() always returns a pointer to the current object.
  6560.           For some collection classes, the "current object" is undefined
  6561.           immediately after the construction of an iterator (or after calling
  6562.           reset()) -- you must position the iterator first before calling
  6563.           key().
  6564.  
  6565.           For most collections, using member function apply() is much faster
  6566.           than using an iterator.  This is particularly true for the sorted
  6567.           collections -- usually a tree has to be traversed, requiring that the
  6568.           parent of a node be stored on a stack.  Function apply() uses the
  6569.           program's stack, while the sorted collection iterator must maintain
  6570.           its own.  The former is much more efficient.
  6571.  
  6572.  
  6573. 15.7 Dictionaries
  6574.  
  6575.  
  6576.  
  6577.           Tools.h++ provides two Smalltalk-like dictionary classes,
  6578.           RWHashDictionary (Dictionary class implemented as a hash table) and
  6579.           RWBTreeDictionary (Dictionary class implemented as a B-Tree), for the
  6580.           storage and retrieval of key-value pairs.  Both keys and values must
  6581.           inherit abstract base class RWCollectable.  Member functions are
  6582.           provided to insert a key-value pair, and to find or remove a key
  6583.           and/or a value, using a key.  Function apply() is no longer
  6584.           appropriate, and a new function applyToKeyAndValue() visits each key-
  6585. Rogue WaveSmalltalk_-like Collection Classes   112
  6586.  
  6587.  
  6588.  
  6589.  
  6590.  
  6591.  
  6592.  
  6593.  
  6594.                         USER'S GUIDE
  6595.  
  6596.           value pair.
  6597.  
  6598.  
  6599.  
  6600.  
  6601.  
  6602.  
  6603.  
  6604.  
  6605.  
  6606.  
  6607.  
  6608.  
  6609.  
  6610.  
  6611.  
  6612.  
  6613.  
  6614.  
  6615.  
  6616.  
  6617.  
  6618.  
  6619.  
  6620.  
  6621.  
  6622.  
  6623.  
  6624.  
  6625.  
  6626.  
  6627.  
  6628.  
  6629.  
  6630.  
  6631.  
  6632.  
  6633.  
  6634.  
  6635.  
  6636.  
  6637.  
  6638.  
  6639.  
  6640. Rogue WaveSmalltalk_-like Collection Classes   113
  6641.  
  6642.  
  6643.  
  6644.  
  6645.  
  6646.  
  6647.  
  6648.  
  6649.                         USER'S GUIDE
  6650.  
  6651.  
  6652. 15.8 A note on how objects are found
  6653.  
  6654.  
  6655.  
  6656.  
  6657.  
  6658.           It is important to note that it is the virtual functions of the
  6659.           object within the collection that gets called when comparing or
  6660.           testing a target for equality, not that of the target.
  6661.  
  6662.  
  6663.           For example, consider the following code fragment:
  6664.  
  6665.             SortedCollection sc;
  6666.             RWCollectableString member;
  6667.  
  6668.             sc.insert(&member);
  6669.  
  6670.             RWCollectableString target;
  6671.             RWCollectableString* p = (RWCollectableString*)sc.find(&target);
  6672.  
  6673.           It is the virtual functions of the objects within the collection,
  6674.           such as member, that will get called, not the virtual functions of
  6675.           target:
  6676.  
  6677.             member.compareTo(&target);  // This will get called.
  6678.             target.compareTo(&member);  // Not this.
  6679.  
  6680. 15.8.1Hash collections
  6681.  
  6682.           Hashing is an efficient method for finding an object within a
  6683.           collection.  All of the collection classes that use it use the same
  6684.           general strategy.  First, member function hash() of the target gets
  6685.           called to find a candidate within the hash table.  Because more than
  6686.           one key can hash to the same value, member function isEqual() of the
  6687.           candidate (see above) is called to confirm the match.  If the match
  6688.           is not confirmed, the algorithm searches for additional candidates by
  6689.           using a secondary hash value, derived from the first hash value.  If
  6690.           this leads to additional candidates, these are tested, in order, by
  6691.           using member function isEqual().  The search stops with either a
  6692.           successful match or when there are no more candidates.
  6693.  
  6694.           In general, because of this combination of primary and secondary
  6695. Rogue WaveSmalltalk_-like Collection Classes   114
  6696.  
  6697.  
  6698.  
  6699.  
  6700.  
  6701.  
  6702.  
  6703.  
  6704.                         USER'S GUIDE
  6705.  
  6706.           hashing values and the complexity of most hashing algorithms, the
  6707.           ordering of the objects within a hash collection will not make a lot
  6708.           of sense.  Hence, when the apply() function or an iterator scans
  6709.           through the hashing table, the objects will not be visited in any
  6710.           particular order.
  6711.  
  6712.  
  6713.  
  6714.  
  6715.  
  6716.  
  6717.  
  6718.  
  6719.  
  6720.  
  6721.  
  6722.  
  6723.  
  6724.  
  6725.  
  6726.  
  6727.  
  6728.  
  6729.  
  6730.  
  6731.  
  6732.  
  6733.  
  6734.  
  6735.  
  6736.  
  6737.  
  6738.  
  6739.  
  6740.  
  6741.  
  6742.  
  6743.  
  6744.  
  6745.  
  6746.  
  6747.  
  6748.  
  6749.  
  6750. Rogue WaveSmalltalk_-like Collection Classes   115
  6751.  
  6752.  
  6753.  
  6754.  
  6755.  
  6756.  
  6757.  
  6758.  
  6759.                         USER'S GUIDE
  6760.  
  6761.  
  6762. 15.9 Storage and retrieval of "Collectable" objects
  6763.  
  6764.  
  6765.  
  6766.           The storage and retrieval of objects that inherit from RWCollectable
  6767.           is a powerful and adaptable feature of the Tools.h++ Class Library.
  6768.           It is done through the following four functions:
  6769.  
  6770.             static RWCollectable*  RWCollectable::restoreFrom(RWvistream&);
  6771.             static RWCollectable*  RWCollectable::restoreFrom(RWFile&);
  6772.             void              RWCollectable::saveOn(RWvostream&) const;
  6773.             void              RWCollectable::saveOn(RWFile&) const
  6774.  
  6775.           These function not only allow the storage and retrieval of
  6776.           collections and their inserted objects, but also their morphology.
  6777.           For example, a collection with multiple pointers to the same object
  6778.           could be be saved and restored.  Or a circularly linked list.  Note
  6779.           that they are not virtual functions -- the declarations (and
  6780.           definitions) reside in the base class RWCollectable.  You should not
  6781.           override them.
  6782.  
  6783.  
  6784.  
  6785.           Note that this ability to restore the morphology of an object is a
  6786.           property of the base class RWCollectable.  It can be used by any
  6787.           object that inherits from RWCollectable, not just the collection
  6788.           classes (which inherit from RWCollection, a derived class of
  6789.           RWCollectable).  We will see how to do this in Section 15.11.
  6790.  
  6791.  
  6792.           Here's an example of the use of these functions that builds on the
  6793.           example of Section 15.2:
  6794.  
  6795.  
  6796.  
  6797.  
  6798.  
  6799.  
  6800.  
  6801.  
  6802.  
  6803.  
  6804.  
  6805. Rogue WaveSmalltalk_-like Collection Classes   116
  6806.  
  6807.  
  6808.  
  6809.  
  6810.  
  6811.  
  6812.  
  6813.  
  6814.                         USER'S GUIDE
  6815.  
  6816.             #include <bintree.h>
  6817.             #include <collstr.h>
  6818.             #include <pstream.h>
  6819.  
  6820.             main()
  6821.             {
  6822.  
  6823.                  // Construct an empty SortedCollection
  6824.                  SortedCollection sc;
  6825.  
  6826.             // Insert, but to make things interesting, add an object twice.
  6827.  
  6828.                  RWCollectableString* george =
  6829.                               new RWCollectableString("George");
  6830.  
  6831.                  sc.insert(george);               // Insert once
  6832.                  sc.insert(new RWCollectableString("Mary"));
  6833.                  sc.insert(george);               // Insert twice
  6834.                  sc.insert(new RWCollectableString("Bill"));
  6835.                  sc.insert(new RWCollectableString("Throkmorton"));
  6836.  
  6837.                  // Store in ascii to standard output:
  6838.                  sc.saveOn(RWpostream(cout));
  6839.             }
  6840.  
  6841.           Note that we have inserted one item into the collection twice.  That
  6842.           is, two items in the collection are identical.  Graphically, the
  6843.           SortedCollection looks something like this:
  6844.  
  6845.  
  6846.  
  6847.           The function saveOn() stores a shallow copy of a RWCollectable.  That
  6848.           is, only only one copy of "George" is stored.
  6849.  
  6850.           The resulting image can be read back in and faithfully restored using
  6851.           the companion member function restoreFrom().  Note, however, that
  6852.           restoreFrom() is a static member function of class RWCollectable.  It
  6853.           reads an object from the file or stream, figures out what type it is,
  6854.           and then creates it off the heap.  It then calls this newly created
  6855.           object's virtual function restoreGuts() (to be described later) to
  6856.           read its state back in from the file or stream.  Function
  6857.           restoreFrom() is declared static because in general, one does not
  6858.           know what type of object to expect when reading from the file, hence
  6859.           one cannot create it until "read-time".
  6860. Rogue WaveSmalltalk_-like Collection Classes   117
  6861.  
  6862.  
  6863.  
  6864.  
  6865.  
  6866.  
  6867.  
  6868.  
  6869.                         USER'S GUIDE
  6870.  
  6871.  
  6872.  
  6873.  
  6874.  
  6875.  
  6876.  
  6877.  
  6878.  
  6879.  
  6880.  
  6881.  
  6882.  
  6883.  
  6884.  
  6885.  
  6886.  
  6887.  
  6888.  
  6889.  
  6890.  
  6891.  
  6892.  
  6893.  
  6894.  
  6895.  
  6896.  
  6897.  
  6898.  
  6899.  
  6900.  
  6901.  
  6902.  
  6903.  
  6904.  
  6905.  
  6906.  
  6907.  
  6908.  
  6909.  
  6910.  
  6911.  
  6912.  
  6913.  
  6914.  
  6915. Rogue WaveSmalltalk_-like Collection Classes   118
  6916.  
  6917.  
  6918.  
  6919.  
  6920.  
  6921.  
  6922.  
  6923.  
  6924.                         USER'S GUIDE
  6925.  
  6926.           Enough said!  It's time to read our collection back in:
  6927.  
  6928.             #include <bintree.h>
  6929.             #include <collstr.h>
  6930.             #include <pstream.h>
  6931.  
  6932.             main()
  6933.             {
  6934.                RWpistream str(cin);
  6935.  
  6936.                SortedCollection* sc =
  6937.                  (SortedCollection*)RWCollectable::restoreFrom(str);  // 1
  6938.  
  6939.                RWCollectableString temp("George");      // 2
  6940.  
  6941.                // Find a "George":
  6942.                RWCollectableString* g =
  6943.                  (RWCollectableString*)sc->find(&temp); // 3
  6944.  
  6945.                // "g" now points to a string with the value "George"
  6946.                // How many occurrences of g are there in the collection?
  6947.  
  6948.                unsigned count = 0;                      // 4
  6949.                SortedCollectionIterator sci(*sc);       // 5
  6950.                RWCollectableString* item;
  6951.                while ( item = (RWCollectableString*)sci() )// 6
  6952.                  if ( item==g ) count++;                // 7
  6953.                cout << count;
  6954.             }
  6955.  
  6956.           Program output:
  6957.  
  6958.             2
  6959.  
  6960.           Here's the line-by-line description:
  6961.  
  6962.           1  On this line, restoreFrom(RWvistream&) reads an object from the
  6963.              input stream cin, figures out that it is a SortedCollection and
  6964.              creates a new SortedCollection off the heap.  Then, it calls
  6965.              SortedCollection's virtual function restoreGuts() which
  6966.              recursively calls restoreFrom() for each member of the
  6967.              collection.  If restoreFrom() encounters a reference to a
  6968.              previous object, it just returns the old address, rather than
  6969.              create a new one off the heap.
  6970. Rogue WaveSmalltalk_-like Collection Classes   119
  6971.  
  6972.  
  6973.  
  6974.  
  6975.  
  6976.  
  6977.  
  6978.  
  6979.                         USER'S GUIDE
  6980.  
  6981.           2  A temporary string with value "George" is created in order to
  6982.              search for a string within the newly created SortedCollection
  6983.              with the same value.
  6984.  
  6985.           3  The SortedCollection is searched for an occurrence of a string
  6986.              with value "George".  The pointer "g" points to such a string.
  6987.  
  6988.           4  Here's how we can prove that there are actually two entries in
  6989.              the collection that point to the same George.  Initialize a
  6990.              counter to zero.
  6991.  
  6992.           5  As before, create an iterator from the collection.
  6993.  
  6994.           6  Iterate through the collection, item by item, returning a pointer
  6995.              for each item.
  6996.  
  6997.           7  Test whether this pointer equals g.  That is, test for identity,
  6998.              not just equality.
  6999.  
  7000.           The program's output is "2", indicating that there are actually two
  7001.           pointers to the same object "George".
  7002.  
  7003.  
  7004. 15.10Designing an RWCollectable class
  7005.  
  7006.  
  7007.  
  7008.           In this section, we discuss the necessary steps to design a new
  7009.           RWCollectable class, perhaps one that you will use in your own work.
  7010.           Once designed, this class can take full advantage of all of the
  7011.           functionality of the Smalltalk-like collection classes.
  7012.  
  7013.  
  7014. 15.10.1   Virtual functions inherited from RWCollectable
  7015.  
  7016.           The Smalltalk-like collection classes require that all objects to be
  7017.           collected inherit the abstract base class RWCollectable, either
  7018.           directly, or by using multiple inheritance.
  7019.  
  7020.           Class RWCollectable declares the following virtual functions (See
  7021.           Part II: Class Reference for a complete description of class
  7022.           RWCollectable):
  7023.  
  7024.  
  7025. Rogue WaveSmalltalk_-like Collection Classes   120
  7026.  
  7027.  
  7028.  
  7029.  
  7030.  
  7031.  
  7032.  
  7033.  
  7034.                         USER'S GUIDE
  7035.  
  7036.             virtual           ~RWCollectable();
  7037.             virtual ClassID        isA() const;
  7038.             virtual int       compareTo(const RWCollectable*) const;
  7039.             virtual unsigned       hash() const;
  7040.             virtual RWBoolean      isEqual(const RWCollectable*) const;
  7041.             virtual RWCollectable* newSpecies() const;
  7042.             virtual void      restoreGuts(RWvistream&);
  7043.             virtual void      restoreGuts(RWFile&);
  7044.             virtual void      saveGuts(RWvostream&) const;
  7045.             virtual void      saveGuts(RWFile&) const;
  7046.  
  7047.           (RWBoolean is a typedef for an int and ClassID is a typedef for an
  7048.           unsigned short.)  Any class that derives from class RWCollectable
  7049.           should be able to understand any of these methods.  Although default
  7050.           definitions are given for all of them in the base class
  7051.           RWCollectable, it is best for the class designer to provide
  7052.           definitions that are tailored to the class at hand.
  7053.  
  7054.  
  7055. 15.10.2   An example
  7056.  
  7057.           The best way to illustrate how to supply appropriate definitions is
  7058.           by using an example.  Suppose we would like to collect and retrieve
  7059.           instances of an Automobile class.  Its declaration might look
  7060.           something like this:
  7061.  
  7062.  
  7063.  
  7064.  
  7065.  
  7066.  
  7067.  
  7068.  
  7069.  
  7070.  
  7071.  
  7072.  
  7073.  
  7074.  
  7075.  
  7076.  
  7077.  
  7078.  
  7079.  
  7080. Rogue WaveSmalltalk_-like Collection Classes   121
  7081.  
  7082.  
  7083.  
  7084.  
  7085.  
  7086.  
  7087.  
  7088.  
  7089.                         USER'S GUIDE
  7090.  
  7091.             class Automobile : public RWCollectable {
  7092.             private:
  7093.                  RWString          marque;   // The manufacturer
  7094.                  double       price;
  7095.                  int          horsepower;
  7096.             public:
  7097.                  // Constructor:
  7098.                  Automobile() { }  // Default constructor
  7099.                  Automobile(RWString name, double pricetag, int hp) :
  7100.                     marque(name), price(pricetag), horsepower(hp) { }
  7101.  
  7102.                  // Inherited from class "RWCollectable":
  7103.                  ClassID      isA() const;
  7104.                  int          compareTo(const RWCollectable*) const;
  7105.                  RWBoolean         isEqual(const RWCollectable*) const;
  7106.                  unsigned          hash() const;
  7107.                  RWCollectable*    newSpecies() const;
  7108.                  void         restoreGuts(RWFile&);
  7109.                  void         restoreGuts(RWvistream&);
  7110.                  void         saveGuts(RWFile&) const;
  7111.                  void         saveGuts(RWvostream&) const;
  7112.                  .
  7113.                  .
  7114.                  .
  7115.                  // Possible, additional, functionality
  7116.             };
  7117.  
  7118.           All collectable classes are required to have a default constructor
  7119.           (i.e., one that takes no arguments).  This is also a good habit to
  7120.           get into when working with C++.  Appropriate definitions for the
  7121.           virtual functions must now be chosen.
  7122.  
  7123.  
  7124.  
  7125.  
  7126.  
  7127.  
  7128.  
  7129.  
  7130.  
  7131.  
  7132.  
  7133.  
  7134.  
  7135. Rogue WaveSmalltalk_-like Collection Classes   122
  7136.  
  7137.  
  7138.  
  7139.  
  7140.  
  7141.  
  7142.  
  7143.  
  7144.                         USER'S GUIDE
  7145.  
  7146.  
  7147. 15.10.3   Object destruction
  7148.  
  7149.           All objects inheriting from class RWCollectable inherit a virtual
  7150.           destructor.  Hence, the actual type of the object need not be known
  7151.           until runtime in order to delete the object.  This allows all items
  7152.           in a collection to be deleted without knowing their actual type.
  7153.  
  7154.  
  7155. 15.10.4   Virtual function isA()
  7156.  
  7157.             virtual ClassID   isA() const;
  7158.  
  7159.           The virtual function isA() returns a "class ID", a unique number that
  7160.           identifies the class.  This number can be used to test which class an
  7161.           object belongs to.  The name "ClassID" is actually a typedef to an
  7162.           unsigned short.  Numbers from 0x8000 (hex) and up are reserved for
  7163.           use by Rogue Wave.  There is a set of class symbols defined in
  7164.           <tooldefs.h> for the Tools.h++ Class Library .  Generally, these
  7165.           follow the pattern of a double underscore followed by the class name
  7166.           with all letters in upper case.  For example:
  7167.  
  7168.             RWCollectableString yogi;
  7169.             yogi.isA() == __RWCOLLECTABLESTRING;  // Evaluates TRUE
  7170.  
  7171.           For our example, here is an appropriate definition:
  7172.  
  7173.             ClassID Automobile::isA() const {return 123;}
  7174.  
  7175. 15.10.5   Virtual function compareTo()
  7176.  
  7177.             virtual int       compareTo(const RWCollectable*) const;
  7178.  
  7179.           The virtual function compareTo() is used to order objects relative to
  7180.           each other in the collection classes that depend on such ordering,
  7181.           such as RWBinaryTree or RWBTree.
  7182.  
  7183.  
  7184.           The function "int compareTo(const RWCollectable*) const" should
  7185.           return a number greater than zero if self is "greater than" the
  7186.           argument, a number less than zero if self is "less than" the
  7187.           argument, and zero if self is "equal to" the argument.  This last
  7188.           case is sometimes referred to as "comparing equal", not be be
  7189.           confused with "is equal" (see Section 15.10.6, below).
  7190. Rogue WaveSmalltalk_-like Collection Classes   123
  7191.  
  7192.  
  7193.  
  7194.  
  7195.  
  7196.  
  7197.  
  7198.  
  7199.                         USER'S GUIDE
  7200.  
  7201.  
  7202.           The definition (and meaning) of whether one object is greater than,
  7203.           less than, or equal to another object is left to the class designer.
  7204.           The default definition, as defined in class RWCollectable, is to
  7205.           compare the two addresses of the objects.
  7206.  
  7207.  
  7208.           Note that the default definition (comparing the addresses of the two
  7209.           objects) should really be thought of as a placeholder -- in practice,
  7210.           it is not very useful and could vary from run-to-run of a program.
  7211.  
  7212.           Here is an example that uses compareTo() as well as isEqual() and
  7213.           hash().
  7214.  
  7215.             RWCollectableString a("a");
  7216.             RWCollectableString b("b");
  7217.             RWCollectableString a2("a");
  7218.  
  7219.             a.compareTo(&b);  // Returns -1
  7220.             a.compareTo(&a2); // Returns 0 ("compares equal")
  7221.             b.compareTo(&a);  // Returns 1
  7222.  
  7223.             a.isEqual(&a2);   // Returns TRUE
  7224.             a.isEqual(&b);    // Returns FALSE
  7225.  
  7226.             a.hash()     // Returns 96 (operating system dependent)
  7227.  
  7228.           Note that the compareTo() function for RWCollectableStrings has been
  7229.           defined to compare strings lexicographically.  Either case-sensitive
  7230.           of case-insensitive comparisons can be done.  See class RWString in
  7231.           Part II: Class Reference for details.
  7232.  
  7233.           Here is a possible definition of compareTo() for our example:
  7234.  
  7235.             int Automobile::compareTo(const RWCollectable* c) const
  7236.             {
  7237.                  const Automobile* ap = (const Automobile*)c;
  7238.                  if ( price == ap->price ) return 0;
  7239.                  return price > ap->price ? 1 : -1;
  7240.             }
  7241.  
  7242.           Here, we are using the price of an automobile as a measure of its
  7243.           "ordering" relative to other automobiles.  There are many other
  7244.           possible choices (such as the horsepower, lexicographical ordering of
  7245. Rogue WaveSmalltalk_-like Collection Classes   124
  7246.  
  7247.  
  7248.  
  7249.  
  7250.  
  7251.  
  7252.  
  7253.  
  7254.                         USER'S GUIDE
  7255.  
  7256.           the marque, etc.).  Which one you chose will depend on your
  7257.           particular problem.
  7258.  
  7259.           Of course, there is a hazard here.  We have been glib in assuming
  7260.           that the actual type of the RWCollectable which c points to is always
  7261.           an Automobile.  If a careless user inserted, say, a
  7262.           RWCollectableString into the collection, then the results of the cast
  7263.           (const Automobile*)c would be invalid and dereferencing it could
  7264.           bring disaster.  This is a glaring deficiency in C++ that the user
  7265.           must constently be aware of.  The necessity for all virtual functions
  7266.           to have all the same signatures requires that they return the lowest
  7267.           common denominator, in this case, class RWCollectable.  The net
  7268.           result is that all compile-time type checking breaks down.
  7269.  
  7270.  
  7271.  
  7272.           One must be careful that the members of a collection are either
  7273.           homogeneous (i.e., all of the same type), or that there is some way
  7274.           of telling them apart.  The member function isA() can be used for
  7275.           this.
  7276.  
  7277.  
  7278.  
  7279. 15.10.6   Virtual function isEqual()
  7280.  
  7281.             RWBoolean         isEqual(const RWCollectable* c) const;
  7282.  
  7283.           The virtual function isEqual() plays a similar role to the "tester
  7284.           function" of the generic collection classes (Section 14.3.1).
  7285.  
  7286.  
  7287.  
  7288.           The function "RWBoolean isEqual(const RWCollectable*)" should return
  7289.           TRUE if the object and its argument are considered a "equal", FALSE
  7290.           otherwise.  The definition of "equal" is left to the class designer.
  7291.           The default definition, as defined in class RWCollectable, is to test
  7292.           the two addresses for equality, that is to test for identity.
  7293.  
  7294.  
  7295.           Note that "isEqual" need not necessarily be defined as "being
  7296.           identical", that is, having the same address (although this is the
  7297.           default), but rather, that they are equivalent in some sense.  In
  7298.           fact, the two objects need not even be of the same type.  The only
  7299.           requirement is that the object passed as an argument inherit type
  7300. Rogue WaveSmalltalk_-like Collection Classes   125
  7301.  
  7302.  
  7303.  
  7304.  
  7305.  
  7306.  
  7307.  
  7308.  
  7309.                         USER'S GUIDE
  7310.  
  7311.           RWCollectable.  However, you are responsible for making sure that any
  7312.           typecasts you do are appropriate.
  7313.  
  7314.           Also note that there is no formal requirement that two objects which
  7315.           "compare equal" (i.e., compareTo() returns zero) must also return
  7316.           TRUE from isEqual(), although it is hard to imagine a situation where
  7317.           this wouldn't be the case.
  7318.  
  7319.           For our example above, an appropriate definition might be:
  7320.  
  7321.             RWBoolean Automobile::isEqual(const RWCollectable* c) const
  7322.             {
  7323.                  const Automobile* ap = (const Automobile*)c;
  7324.  
  7325.                  return  marque == ap->marque &&
  7326.                          horsepower == ap->horsepower &&
  7327.                          price == ap->price;
  7328.             }
  7329.  
  7330.           Here, we are casting the variable c, a pointer to the abstract base
  7331.           class RWCollectable, to a pointer to an Automobile, which we are
  7332.           calling "ap".  Then all of the members of Automobile are checked for
  7333.           equality.
  7334.  
  7335.  
  7336. 15.10.7   Virtual function hash()
  7337.  
  7338.             unsigned          hash() const;
  7339.  
  7340.  
  7341.           The function hash() should return an appropriate hashing value for
  7342.           the object.
  7343.  
  7344.  
  7345.           A possible definition for hash() for our example might be:
  7346.  
  7347.             unsigned Automobile::hash() const
  7348.             {
  7349.                  return marque.hash();
  7350.             }
  7351.  
  7352.           Here, we have just returned the hash value of the manufacturer's
  7353.           name.
  7354.  
  7355. Rogue WaveSmalltalk_-like Collection Classes   126
  7356.  
  7357.  
  7358.  
  7359.  
  7360.  
  7361.  
  7362.  
  7363.  
  7364.                         USER'S GUIDE
  7365.  
  7366.  
  7367. 15.10.8   Virtual function newSpecies()
  7368.  
  7369.           The job of this function is to return a pointer to a brand new object
  7370.           of the same class as self.  Although you are responsible for putting
  7371.           in the prototype in the class declaration, a macro to be described in
  7372.           Section 15.10.11 will supply an appropriate definition.
  7373.  
  7374.  
  7375. 15.10.9   Virtual functions saveGuts(RWFile&) and saveGuts(RWvostream&)
  7376.  
  7377.           These virtual functions are responsible for storing the internal
  7378.           state of an RWCollectable on either a binary file (using class
  7379.           RWFile) or on a virtual output stream (an RWvostream).  This allows
  7380.           the object to be recovered at some later time.  Here is a possible
  7381.           definition:
  7382.  
  7383.             void
  7384.             Automobile::saveGuts(RWFile& file)
  7385.             {
  7386.                  marque.saveOn(file);
  7387.                  file.Write(price);
  7388.                  file.Write(horsepower);
  7389.             }
  7390.  
  7391.             void
  7392.             Automobile::saveGuts(RWvostream& strm)
  7393.             {
  7394.                  marque.saveOn(strm);
  7395.                  strm << price << horsepower;
  7396.             }
  7397.  
  7398.           Note how member function RWString::saveOn() was used to save the
  7399.           member data marque.  Also note how price and horsepower were written
  7400.           out in function saveGuts(RWvostream&) without any formatting (e.g.,
  7401.           separating blanks) -- the specializing virtual output stream will do
  7402.           this, if necessary.
  7403.  
  7404.  
  7405. 15.10.10  Virtual functions restoreGuts(RWFile&) and restoreGuts(RWvistream&)
  7406.  
  7407.           In a similar manner, these virtual functions are used to restore the
  7408.           internal state of an RWCollectable from a file or stream:
  7409.  
  7410. Rogue WaveSmalltalk_-like Collection Classes   127
  7411.  
  7412.  
  7413.  
  7414.  
  7415.  
  7416.  
  7417.  
  7418.  
  7419.                         USER'S GUIDE
  7420.  
  7421.             void
  7422.             Automobile::restoreGuts(RWFile& file)
  7423.             {
  7424.                  marque.restoreFrom(file);
  7425.                  file.Read(price);
  7426.                  file.Read(horsepower);
  7427.             }
  7428.  
  7429.             void
  7430.             Automobile::restoreGuts(RWvistream& strm)
  7431.             {
  7432.                  marque.restoreFrom(strm);
  7433.                  strm >> price >> horsepower;
  7434.             }
  7435.  
  7436. 15.10.11  Putting it all together
  7437.  
  7438.           There is one final detail that must be attended to when creating a
  7439.           new RWCollectable class.  One must supply a function to create a new
  7440.           instance of your new class.  This is done automatically for you by a
  7441.           macro DEFINE_COLLECTABLE(type).  For our example the following must
  7442.           be included somewhere in a .cpp file:
  7443.  
  7444.             DEFINE_COLLECTABLE(Automobile)
  7445.  
  7446.           This magic incantation will allow a new instance of your class to be
  7447.           created given its ClassID:
  7448.  
  7449.             Automobile* newAuto = (Automobile*)theFactory->create(123);
  7450.  
  7451.           The pointer theFactory is a global pointer that points to a one-of-a-
  7452.           kind global instance of class RWFactory, used to create new instances
  7453.           of any class, given its ClassID.  The use of RWFactory is generally
  7454.           transparent to the user.  See Part II: Class Reference for more
  7455.           details on RWFactory.
  7456.  
  7457.           The macro DEFINE_COLLECTABLE also supplies a definition for the
  7458.           member function newSpecies().
  7459.  
  7460.           Here then, is the complete listing for our class Automobile:
  7461.  
  7462.  
  7463.  
  7464.  
  7465. Rogue WaveSmalltalk_-like Collection Classes   128
  7466.  
  7467.  
  7468.  
  7469.  
  7470.  
  7471.  
  7472.  
  7473.  
  7474.                         USER'S GUIDE
  7475.  
  7476.             AUTO.H:
  7477.  
  7478.             #ifndef __AUTO_H__
  7479.             #define __AUTO_H__
  7480.  
  7481.             class Automobile : public RWCollectable {
  7482.             private:
  7483.                  RWString          marque;   // The manufacturer
  7484.                  double       price;
  7485.                  int          horsepower;
  7486.             public:
  7487.                  // Constructor:
  7488.                  Automobile() { }  // Default constructor
  7489.                  Automobile(RWString name, double pricetag, int hp) :
  7490.                     marque(name), price(pricetag), horsepower(hp) { }
  7491.  
  7492.                  // Inherited from class "RWCollectable":
  7493.                  ClassID      isA() const;
  7494.                  int          compareTo(const RWCollectable*) const;
  7495.                  RWBoolean         isEqual(const RWCollectable*) const;
  7496.                  unsigned          hash() const;
  7497.                  RWCollectable*    newSpecies() const;
  7498.                  void         restoreGuts(RWFile&);
  7499.                  void         restoreGuts(RWvistream&);
  7500.                  void         saveGuts(RWFile&) const;
  7501.                  void         saveGuts(RWvostream&) const;
  7502.             };
  7503.             #endif
  7504.  
  7505.             AUTO.CPP:
  7506.  
  7507.             // Magic incantation; see Section 15.10.11:
  7508.             DEFINE_COLLECTABLE(Automobile)
  7509.  
  7510.             // See Section 15.10.4:
  7511.             ClassID
  7512.             Automobile::isA() const
  7513.             {
  7514.               return 123;
  7515.             }
  7516.  
  7517.  
  7518.  
  7519.  
  7520. Rogue WaveSmalltalk_-like Collection Classes   129
  7521.  
  7522.  
  7523.  
  7524.  
  7525.  
  7526.  
  7527.  
  7528.  
  7529.                         USER'S GUIDE
  7530.  
  7531.             // See Section 15.10.5:
  7532.             int
  7533.             Automobile::compareTo(const RWCollectable* c) const
  7534.             {
  7535.                  const Automobile* ap = (const Automobile*)c;
  7536.                  if ( price == ap->price ) return 0;
  7537.                  return price > ap->price ? 1 : -1;
  7538.             }
  7539.  
  7540.             // See Section 15.10.6:
  7541.             RWBoolean
  7542.             Automobile::isEqual(const RWCollectable* c) const
  7543.             {
  7544.                  const Automobile* ap = (const Automobile*)c;
  7545.  
  7546.                  return  marque == ap->marque &&
  7547.                          horsepower == ap->horsepower &&
  7548.                          price == ap->price;
  7549.             }
  7550.  
  7551.             // See Section 15.10.7:
  7552.             unsigned
  7553.             Automobile::hash() const
  7554.             {
  7555.                  return marque.hash();
  7556.             }
  7557.  
  7558.             // See Section 15.10.9:
  7559.             void
  7560.             Automobile::saveGuts(RWFile& file)
  7561.             {
  7562.                  marque.saveOn(file);
  7563.                  file.Write(price);
  7564.                  file.Write(horsepower);
  7565.             }
  7566.  
  7567.             // See Section 15.10.9:
  7568.             void
  7569.             Automobile::saveGuts(RWvostream& strm)
  7570.             {
  7571.                  marque.saveOn(strm);
  7572.                  strm << price << horsepower;
  7573.             }
  7574.  
  7575. Rogue WaveSmalltalk_-like Collection Classes   130
  7576.  
  7577.  
  7578.  
  7579.  
  7580.  
  7581.  
  7582.  
  7583.  
  7584.                         USER'S GUIDE
  7585.  
  7586.             // See Section 15.10.10:
  7587.             void
  7588.             Automobile::restoreGuts(RWFile& file)
  7589.             {
  7590.                  marque.restoreFrom(file);
  7591.                  file.Read(price);
  7592.                  file.Read(horsepower);
  7593.             }
  7594.  
  7595.             // See Section 15.10.10:
  7596.             void
  7597.             Automobile::restoreGuts(RWvistream& strm)
  7598.             {
  7599.                  marque.restoreFrom(strm);
  7600.                  strm >> price >> horsepower;
  7601.             }
  7602.  
  7603. 15.10.12  Summary
  7604.  
  7605.           In general, you may not have to supply definitions for all of these
  7606.           virtual functions.  For example, if you know that your class will
  7607.           never be used in sorted collections, then you do not need a
  7608.           definition for compareTo().  Nevertheless, it is a good idea to do it
  7609.           anyway because you never know!
  7610.  
  7611.  
  7612. 15.11More on storing and retrieving RWCollectables
  7613.  
  7614.  
  7615.  
  7616.           The member functions saveOn() and restoreFrom() are responsible for
  7617.           maintaining the morphology of a class (i.e., the correct
  7618.           relationships between pointers) when the class is stored and
  7619.           restored.  Note that they are not virtual functions -- you need not
  7620.           redefine them.  In fact, as mentioned in Section 15.9, restoreFrom()
  7621.           is a static function and is not associated with any particular
  7622.           instance of a class.
  7623.  
  7624.           When working with RWCollectables, it is useful to understand how
  7625.           these functions work.  Here is a brief description.
  7626.  
  7627.           When you call saveOn() for the first time for any collectable object,
  7628.           an IdentityDictionary is created internally.  The object's address
  7629.           (i.e., "this") is put in the table, along with its ordinal position
  7630. Rogue WaveSmalltalk_-like Collection Classes   131
  7631.  
  7632.  
  7633.  
  7634.  
  7635.  
  7636.  
  7637.  
  7638.  
  7639.                         USER'S GUIDE
  7640.  
  7641.           in the output file (the first, the second, etc.).  Once this has been
  7642.           done, a call is made to the virtual function saveGuts().  Because
  7643.           this is a virtual function, the call will go to the derived class's
  7644.           definition of saveGuts().  As we have seen, the job of saveGuts() is
  7645.           to store the internals of the object.  If the object contains
  7646.           pointers to other objects (as all of the collection classes do, as
  7647.           well as many other classes), then the object's saveGuts(), if it has
  7648.           been written correctly, will call saveOn() recursively for each of
  7649.           these pointers.  Subsequent invocations of saveOn() do not create a
  7650.           new IdentityDictionary, but do store the object's address in the
  7651.           already existing dictionary.  If an address is encountered which is
  7652.           identical to a previously written object's address, then saveGuts()
  7653.           is not called.  Instead, a reference is written that this object is
  7654.           identical to some previous object (say, the sixth).
  7655.  
  7656.           When the entire collection has been traversed and the initial call to
  7657.           saveGuts() returns, then the IdentityDictionary is deleted and the
  7658.           initial call to saveOn() returns.
  7659.  
  7660.           The function restoreFrom() essentially reverses this process and,
  7661.           when encountering a reference to an object that has already been
  7662.           created, merely returns the address of the old object rather than
  7663.           asking the RWFactory to create a new one.
  7664.  
  7665.           Here is a more sophisticated example of a class that uses these
  7666.           feature:
  7667.  
  7668.             class Tangle : public RWCollectable {
  7669.                  Tangle*      nextTangle;
  7670.                  int          someData;
  7671.  
  7672.             public:
  7673.  
  7674.                  Tangle(Tangle* t = 0) {nextTangle=t; someData = 0;}
  7675.  
  7676.                  // Redefined from class RWCollectable:
  7677.                  virtual void saveGuts(RWFile&) const;
  7678.                  virtual void restoreGuts(RWFile&);
  7679.                  .
  7680.                  .
  7681.                  .
  7682.             };
  7683.  
  7684.  
  7685. Rogue WaveSmalltalk_-like Collection Classes   132
  7686.  
  7687.  
  7688.  
  7689.  
  7690.  
  7691.  
  7692.  
  7693.  
  7694.                         USER'S GUIDE
  7695.  
  7696.             void
  7697.             Tangle::saveGuts(RWFile& file) const
  7698.             {
  7699.                  // Store any member data:
  7700.                  file.Write(someData);
  7701.  
  7702.                  // Then call saveOn() for the next object:
  7703.                  if(nextTangle) nextTangle->saveOn(file);
  7704.                  else nilCollectable->saveOn(file);
  7705.             }
  7706.  
  7707.             void
  7708.             Tangle::restoreGuts(RWFile& file)
  7709.  
  7710.             {
  7711.                  // Restore my state:
  7712.                  file.Read(someData);
  7713.  
  7714.                  // Then get the address of the next object:
  7715.                  nextTangle = (Tangle*)restoreFrom(file);
  7716.                  if (nextTangle==nilCollectable) nextTangle = 0;
  7717.             }
  7718.  
  7719.           This class implements a (potentially) circularly linked list.  What
  7720.           happens?  When function saveOn(RWFile&) is called for the first time
  7721.           for an instance of Tangle, it sets up the IdentityDictionary, as
  7722.           described above, and then calls the Tangle's saveGuts() whose
  7723.           definition is shown above.  This definition stores any member data of
  7724.           Tangle, then calls saveOn() for the next link.  This recursion
  7725.           continues on around the chain.
  7726.  
  7727.           If the chain ends with a nil object (i.e., nextTangle is zero), then
  7728.           we mark it with the one-of-a-kind RWCollectable called
  7729.           nilCollectable.  This special object is useful when the number of
  7730.           items is not known or if there is no other way to mark the end of a
  7731.           chain of objects.
  7732.  
  7733.           On the other hand, if the list is circular, then a call to saveOn()
  7734.           will eventually be made for the first instance of Tangle again, the
  7735.           one that started this whole chain.  When this happens, saveOn() will
  7736.           recognize that it has already seen this instance before and, rather
  7737.           than call saveGuts() again, will just make a reference to the
  7738.           previously written link.  This stops the series of recursive calls to
  7739.           saveOn() and the stack then unwinds.
  7740. Rogue WaveSmalltalk_-like Collection Classes   133
  7741.  
  7742.  
  7743.  
  7744.  
  7745.  
  7746.  
  7747.  
  7748.  
  7749.                         USER'S GUIDE
  7750.  
  7751.           Restoration of the chain is done in a similar manner.  A call to
  7752.           restoreFrom() will either create a new object off the heap and return
  7753.           a pointer to it, or return the address of a previously read object.
  7754.           The end of a non-circular chain can be detected by testing against
  7755.           the nilCollectable object.  In the case of a circular chain, the
  7756.           recursive calls to restoreFrom() and restoreGuts() will stop and the
  7757.           stack unwinds.
  7758.  
  7759.  
  7760.  
  7761.           Note that because restoreFrom() returns a new item off the heap you
  7762.           are responsible for deleting it when you are done with it.
  7763.  
  7764.  
  7765.  
  7766.  
  7767.  
  7768.  
  7769.  
  7770.  
  7771.  
  7772.  
  7773.  
  7774.  
  7775.  
  7776.  
  7777.  
  7778.  
  7779.  
  7780.  
  7781.  
  7782.  
  7783.  
  7784.  
  7785.  
  7786.  
  7787.  
  7788.  
  7789.  
  7790.  
  7791.  
  7792.  
  7793.  
  7794.  
  7795. Rogue WaveSmalltalk_-like Collection Classes   134
  7796.  
  7797.  
  7798.  
  7799.  
  7800.  
  7801.  
  7802.  
  7803.  
  7804.                         USER'S GUIDE
  7805.  
  7806.  
  7807. 15.11.1   Reading and writing collections
  7808.  
  7809.           All of the Smalltalk-like collection classes inherit the abstract
  7810.           base class RWCollection.  Class RWCollection has a version of
  7811.           saveGuts() and restoreGuts() built into it that is sufficient for
  7812.           most collection classes.  RWCollection::saveGuts() works by
  7813.           repeatedly calling saveOn() for each item in the collection.
  7814.           Similarly, RWCollection::restoreGuts() works by repeatedly calling
  7815.           restoreFrom(), followed by insert(), for each item in the collection.
  7816.  
  7817.           If you decide to write your own collection classes and inherit from
  7818.           class RWCollection, you will rarely have to define your own
  7819.           saveGuts() or restoreGuts().
  7820.  
  7821.           There are exceptions.  For example, class RWBinaryTree has its own
  7822.           version of restoreGuts().  This is necessary because during a restore
  7823.           the incoming items will be inserted in order, resulting in a severely
  7824.           unbalanced tree (essentially, you would get the degenerate case of a
  7825.           linked list).  Hence, RWBinaryTree's version of restoreGuts() first
  7826.           calls RWCollection::restoreGuts() and then RWBinaryTree::balance(),
  7827.           which then balances the tree.
  7828.  
  7829.  
  7830. 15.12Architectural notes
  7831.  
  7832.  
  7833.  
  7834.           In Section 15.10, we built a Automobile class by inheriting from
  7835.           RWCollectable.  If we had an existing Auto class at hand, we might
  7836.           have been able to use multiple inheritance to create a new class with
  7837.           the functionality of both Auto and RWCollectable, perhaps saving
  7838.           ourselves some work:
  7839.  
  7840.             class CollectableAuto : public RWCollectable, public Auto {
  7841.                  .
  7842.                  .
  7843.                  .
  7844.             };
  7845.  
  7846.           This is the approach taken by many of the Rogue Wave collectable
  7847.           classes (e.g., class RWCollectableString, which inherits both class
  7848.           RWCollectable and class RWString).  The general idea is to create
  7849.           your object first, and then tack on the RWCollectable class, making
  7850. Rogue WaveSmalltalk_-like Collection Classes   135
  7851.  
  7852.  
  7853.  
  7854.  
  7855.  
  7856.  
  7857.  
  7858.  
  7859.                         USER'S GUIDE
  7860.  
  7861.           the whole thing collectable.  This way, you will be able to use your
  7862.           objects for other things, in other situations, where you might not
  7863.           want to inherit from class RWCollectable.
  7864.  
  7865.  
  7866.  
  7867.  
  7868.  
  7869.  
  7870.  
  7871.  
  7872.  
  7873.  
  7874.  
  7875.  
  7876.  
  7877.  
  7878.  
  7879.  
  7880.  
  7881.  
  7882.  
  7883.  
  7884.  
  7885.  
  7886.  
  7887.  
  7888.  
  7889.  
  7890.  
  7891.  
  7892.  
  7893.  
  7894.  
  7895.  
  7896.  
  7897.  
  7898.  
  7899.  
  7900.  
  7901.  
  7902.  
  7903.  
  7904.  
  7905. Rogue WaveSmalltalk_-like Collection Classes   136
  7906.  
  7907.  
  7908.  
  7909.  
  7910.  
  7911.  
  7912.  
  7913.  
  7914.                         USER'S GUIDE
  7915.  
  7916.           There is another good reason for using this approach: avoiding
  7917.           ambiguous base classes.  Here's an example:
  7918.             class A { };
  7919.  
  7920.             class B : public A { };
  7921.  
  7922.             class C : public A { };
  7923.  
  7924.             class D : public B, public C { };
  7925.  
  7926.             void fun(A&);
  7927.  
  7928.             main () {
  7929.                  D  d;
  7930.                  fun(d); // Which A ?
  7931.             }
  7932.  
  7933.           There are two approaches to disambiguating the call to fun().  Either
  7934.           change it to:
  7935.             fun((B)d);   // We mean B's occurrence of A
  7936.           or make A a virtual base class.
  7937.           The first approach is error prone -- the user must know the details
  7938.           of the inheritance tree so as to make the proper cast.
  7939.           The second approach, making A a virtual base class, solves this
  7940.           problem, but introduces another: it becomes nearly impossible to make
  7941.           a cast back to the derived class!  This is because there are now two
  7942.           or more paths back through the inheritance hierarchy or, if you
  7943.           prefer a more physical reason, the compiler implements virtual base
  7944.           classes as pointers to the base class and you can't follow a pointer
  7945.           backwards.  The only solution is to exhaustively search all possible
  7946.           paths in the object's inheritance hierarchy, looking for a match.
  7947.           (This is the approach of the NIH Classes.)  Such a solution is slow
  7948.           (it must be done for every cast, although the search can be speeded
  7949.           up by "memoizing" the resulting addresses), bulky and always
  7950.           complicated.  We decided that this was unacceptable.
  7951.           Hence, we chose the first route.  This can be made acceptable by
  7952.           keeping the inheritance trees simple by not making everything derive
  7953.           from the same base class.  Hence, rather than using a large secular
  7954.           base class (sometimes dubbed the "cosmic object"; an example is
  7955.           Smalltalk's "Object") with lots of functionality, we have chosen to
  7956.           tease out the separate bits of functionality into separate, smaller
  7957.           base classes.
  7958.           The idea is to first build your object, then tack on the base class
  7959.           that will supply the functionality that you need (such as
  7960. Rogue WaveSmalltalk_-like Collection Classes   137
  7961.  
  7962.  
  7963.  
  7964.  
  7965.  
  7966.  
  7967.  
  7968.  
  7969.                         USER'S GUIDE
  7970.  
  7971.           collectability), thus avoiding multiple base classes of the same type
  7972.           and the resulting ambiguous calls.
  7973.  
  7974.  
  7975.  
  7976.  
  7977.  
  7978.  
  7979.  
  7980.  
  7981.  
  7982.  
  7983.  
  7984.  
  7985.  
  7986.  
  7987.  
  7988.  
  7989.  
  7990.  
  7991.  
  7992.  
  7993.  
  7994.  
  7995.  
  7996.  
  7997.  
  7998.  
  7999.  
  8000.  
  8001.  
  8002.  
  8003.  
  8004.  
  8005.  
  8006.  
  8007.  
  8008.  
  8009.  
  8010.  
  8011.  
  8012.  
  8013.  
  8014.  
  8015. Rogue WaveSmalltalk_-like Collection Classes   138
  8016.  
  8017.  
  8018.  
  8019.  
  8020.  
  8021.  
  8022.  
  8023.  
  8024.  
  8025.  
  8026.  
  8027.  
  8028.  
  8029.  
  8030.  
  8031.                                                           S e c t i o n    1 6 
  8032.  
  8033.  
  8034.                                        Implementation NotesImplementation notes
  8035.  
  8036.  
  8037.  
  8038.  
  8039. 16.1 Errors Errors -- when bad things happen to good programs
  8040.  
  8041.  
  8042.  
  8043.           Thinking about error handling is like thinking about where the
  8044.           garbage man hauls your trash -- it's a messy, unpredicatable, and
  8045.           sour topic, one that we don't like to think about.  Yet, to write
  8046.           robust code, think about it we must.
  8047.  
  8048.           The Rogue Wave class libraries use an extensive and complete error
  8049.           handling facility, all based on the same model.  Errors are divided
  8050.           into three categories: violated preconditions, invalid input, and
  8051.           asynchronous errors.  The difference between them depends on who
  8052.           screwed up: the programmer, the final end user, or some
  8053.           external/internal software error.  Each type of error requires a
  8054.           different approach to how it is handled.  The following sections
  8055.           describe these approaches and how you can change how they are
  8056.           handled.
  8057.  
  8058.  
  8059. 16.1.1Violated preconditions
  8060.  
  8061.           This type of error deals with failures to follow the programming
  8062.           rules set out by the Tools.h++ classes.  If an indexing operator says
  8063.           not to ask for an index greater than a vector's length and you do so,
  8064.           then that is a violated precondition.
  8065.  
  8066.           A more formal description is given by Meyer (1988).  Briefly,
  8067.           functions are regarded as a "contract" between caller and callee.  If
  8068.           the caller abides by a set of "preconditions", then the callee
  8069.           guarantees to return results that satisfy a set of "postconditions".
  8070. Rogue Wave       Implementation Notes   139
  8071.  
  8072.  
  8073.  
  8074.  
  8075.  
  8076.  
  8077.  
  8078.  
  8079.                         USER'S GUIDE
  8080.  
  8081.           Typically, preconditions are such things as requiring that an index
  8082.           be within a set of bounds, that pointers be non-nil, etc.  The ideal
  8083.           goal is that these types of errors will never happen.  Because they
  8084.           will never happen, there is no need to provide a recovery mechanism
  8085.           or even to detect them!
  8086.  
  8087.           But, of course, they do happen.  So, how do you guard against them?
  8088.           How do you detect them?  The Rogue Wave classes have an extensive set
  8089.           of PRECONDITION and POSTCONDITION clauses at the beginning and end of
  8090.           critical functions.  They can be activated by compiling the entire
  8091.           library with the preprocessor flag "DEBUG" defined.  The entire
  8092.           library must be compiled with a single setting of the flag -- either
  8093.           defined or not defined.  The resultant library will be slightly
  8094.           larger and slightly slower.  See the appropriate makefile for
  8095.           additional directions.
  8096.  
  8097.           The pre- and postconditions are either implemented with "asserts" --
  8098.           a failure will cause the offending condition to be printed out, along
  8099.           with the file and line number where it occurred -- or through the
  8100.           Rogue Wave error facility.
  8101.  
  8102.           Again, the assumption is that these are programming errors and can
  8103.           and should be avoided.  Hence, there are no facilities for error
  8104.           recovery.
  8105.  
  8106.  
  8107. 16.1.2Invalid input
  8108.  
  8109.           This type of error is caused by an invalid input, usually on the part
  8110.           of the final end user (e.g., the user of the graphics program you are
  8111.           writing), rather than the programmer.  For example, a user might
  8112.           specify a date of "31 June 1985", a day that doesn't exist.  It would
  8113.           be a mean-spirited program that simply aborted when given such a
  8114.           date.  It would be much preferred if the date's invalidity could be
  8115.           explicitly recognized, to be rejected or corrected.
  8116.  
  8117.           Nevertheless, the line between invalid input and a violated
  8118.           precondition can be fuzzy.  For example, the rules could say, "don't
  8119.           give me an invalid date" and then the programmer would be responsible
  8120.           for detecting the bad date before handing it to the Tools.h++
  8121.           routines.  Of course, this is a lot of work, and (in this example)
  8122.           the RWDate class would probably be better equipped than the caller to
  8123.           determine the validity of the date.  Hence, this is an approach that
  8124.           is generally not taken.
  8125. Rogue Wave       Implementation Notes   140
  8126.  
  8127.  
  8128.  
  8129.  
  8130.  
  8131.  
  8132.  
  8133.  
  8134.                         USER'S GUIDE
  8135.  
  8136.           How are these kinds of errors dealt with?  Generally, by either
  8137.           returning a "special value" (perhaps a nil pointer), or by use of a
  8138.           member function that tests the validity of the resultant object.
  8139.           Continuing with the RWDate example,
  8140.  
  8141.             main() {
  8142.               RWDate theDate(31, "June", 1985);
  8143.  
  8144.               if( theDate.isValid() )
  8145.                 cout << "OK!\n";
  8146.               else
  8147.                 cout << "Not ok!\n";
  8148.             }
  8149.  
  8150.           In the case of dates, the member function isValid() is available for
  8151.           detecting the validity of the resultant RWDate.  The above program
  8152.           would print out "Not ok!".
  8153.  
  8154.  
  8155. 16.1.3Asynchronous errors
  8156.  
  8157.           These kinds of errors are difficult to predict and are generally due
  8158.           to a failure on the part of the operating system.  By far the most
  8159.           common example is "out of memory".  Others are failure to open a
  8160.           file, perhaps due to the lack of disk space, or a hardware failure.
  8161.  
  8162.           The usual response to these types of errors by the Tools.h++ Class
  8163.           Library is to throw an exception.  At the time of this writing, the
  8164.           syntax and mechanism for exception handling, as outlined by Ellis and
  8165.           Stroustrup (1990), has been accepted into the ANSI X3J16 C++ draft.
  8166.           Unfortunately, none of the major commercial compiler manufacturers
  8167.           have implemented it.
  8168.  
  8169.           The Rogue Wave class libraries have been built to allow a smooth
  8170.           transition to exception handling when it becomes available.  For now,
  8171.           the default error handler posts a note (either to standard output or
  8172.           to a Windows MessageBox, depending on whether or not the library has
  8173.           been compiled as a DLL) with the type of error, then aborts the
  8174.           program.  This default handler can be changed.
  8175.  
  8176.           The code to implement exception handling is in place.  Assuming that
  8177.           the syntax doesn't undergo a major change, all that is required to
  8178.           activate it is to define the preprocessor macro HAS_EXCEPTIONS and
  8179.           recompile the library.  Here's how to use it:
  8180. Rogue Wave       Implementation Notes   141
  8181.  
  8182.  
  8183.  
  8184.  
  8185.  
  8186.  
  8187.  
  8188.  
  8189.                         USER'S GUIDE
  8190.  
  8191.             main()
  8192.             {
  8193.               try {
  8194.                 RWFile file("file.dat");     // Might fail, due to hardware
  8195.               }
  8196.               catch(RWErrObject eobj) {
  8197.                 if( eobj.number() == CORE_OPERR )
  8198.                   cerr << "Could not open file\n";
  8199.                 else{
  8200.                   cerr << "Unexpected error\n";
  8201.                   exit(eobj.number());
  8202.                 }
  8203.               }
  8204.               // Code that depends on "file" being opened
  8205.             }
  8206.  
  8207.  
  8208.           Don't try this if you compiler doesn't implement exceptions!
  8209.  
  8210.  
  8211.  
  8212.  
  8213.  
  8214.  
  8215.  
  8216.  
  8217.  
  8218.  
  8219.  
  8220.  
  8221.  
  8222.  
  8223.  
  8224.  
  8225.  
  8226.  
  8227.  
  8228.  
  8229.  
  8230.  
  8231.  
  8232.  
  8233.  
  8234.  
  8235. Rogue Wave       Implementation Notes   142
  8236.  
  8237.  
  8238.  
  8239.  
  8240.  
  8241.  
  8242.  
  8243.  
  8244.                         USER'S GUIDE
  8245.  
  8246.  
  8247. 16.1.4Changing the default error handler
  8248.  
  8249.           The global function setRWErrHandler(RWErrHandler routine) is
  8250.           available for changing the default error handler.  It takes an
  8251.           argument of type RWErrHandler which is a typedef:
  8252.  
  8253.             typedef void (* RWErrHandler)(RWErrObject, va_list);
  8254.  
  8255.           That is, a pointer to a function with prototype:
  8256.  
  8257.             void    yourErrorHandler(RWErrObject, va_list);
  8258.  
  8259.           where yourErrorHandler is the name of your substitute error handler.
  8260.           The first argument, RWErrObject is a class that packages together the
  8261.           error number, its severity, and the class that invoked the error.
  8262.           See the Class Reference guide for more information.  The second
  8263.           argument is a variable argument list of the style10 of Ellis and
  8264.           Stroustrup (1990), Section 8.3, and is defined in the header file
  8265.           <stdarg.h>.  It contains supplemental information about the error.
  8266.  
  8267.  
  8268. 16.1.5Error numbers and messages
  8269.  
  8270.           The error numbers are listed in the header files <coreerr.h> and
  8271.           <toolerr.h>.  The former contains errors that can be thrown by any of
  8272.           the Rogue Wave class libraries, the latter are specific to the
  8273.           Tools.h++ Class Library.  If you have source code, you can see the
  8274.           associated error messages in files coreerr.cpp and toolerr.cpp,
  8275.           respectively, and surmise the auxilary information contained in the
  8276.           va_list.  For example, the error TOOL_INDEX is listed in toolerr.cpp
  8277.           as:
  8278.  
  8279.             RWFATAL,     "[INDEX] Index (%d) out of range [0->%d]"
  8280.  
  8281.           This means that the default disposition of this error is to abort
  8282.           (RWFATAL), that the first argument in the va_list is the index the
  8283.           user attempted to use, and the second argument is the highest allowed
  8284.           index.
  8285.  
  8286.                     
  8287.  
  8288.           10   The "variable argument list" syntax is also defined by
  8289.                ANSI C.
  8290. Rogue Wave       Implementation Notes   143
  8291.  
  8292.  
  8293.  
  8294.  
  8295.  
  8296.  
  8297.  
  8298.  
  8299.                         USER'S GUIDE
  8300.  
  8301.  
  8302. 16.2 Dynamic Link LibraryDLL" \t ""
  8303.  
  8304.  
  8305.  
  8306.           The Tools.h++ Class Library can be linked as a Microsoft Windows 3.0
  8307.           Dynamic Link Library (DLL).  In a DLL, linking occurs at runtime when
  8308.           the routine is actually needed.  This results in much smaller
  8309.           executables because routines are pulled in only on an "as needed"
  8310.           basis.  Another advantage is that many applications can share the
  8311.           same code, rather than having it duplicated in each application.
  8312.  
  8313.           A prebuilt large model DLL, using the Borland C++ compiler, comes
  8314.           with Tools.h++.
  8315.  
  8316.           Because this is a rapidly evolving area of Windows and C++
  8317.           technology, be sure to see the file DLL.DOC, included on your
  8318.           distribution disk, for any last minute changes.
  8319.  
  8320.  
  8321.  
  8322.  
  8323. Figure 16-1.   The Demo program window.
  8324.  
  8325. 16.2.1Example
  8326.  
  8327.           This section discusses a sample Windows application that uses the
  8328.           Tools.h++ DLL -- yet another tiresome "Hello World" example.  The
  8329.           program is somewhat unique in that it maintains a linked list of
  8330.           "Drawable" objects that can be inserted into the window at run time.
  8331.           This list is implemented using class RWSlistCollectables.  The
  8332.           program can be found in the subdirectory DLLDEMO.  This discussion
  8333.           assumes that you are somewhat familiar with Windows 3.0 programming,
  8334.           but not with C++'s relationship to it.
  8335.  
  8336.  
  8337.  
  8338.  
  8339.  
  8340.  
  8341.  
  8342.  
  8343.  
  8344.  
  8345. Rogue Wave       Implementation Notes   144
  8346.  
  8347.  
  8348.  
  8349.  
  8350.  
  8351.  
  8352.  
  8353.  
  8354.                         USER'S GUIDE
  8355.  
  8356.           Here's the main program.
  8357.  
  8358.             DEMO.CPP
  8359.  
  8360.             /*
  8361.              * Sample Windows 3.0 program, using the Tools.h++ DLL.
  8362.              */
  8363.  
  8364.             #include "demowind.h"
  8365.  
  8366.             int PASCAL
  8367.             WinMain(HANDLE hInstance, HANDLE hPrevInstance,
  8368.                     LPSTR , int nCmdShow)               // 1
  8369.             {
  8370.               // Create an instance of the "DemoWindow" class:
  8371.               DemoWindow ww(hInstance, hPrevInstance, nCmdShow); // 2
  8372.  
  8373.               // Add some items to it:
  8374.               ww.insert( new RWRectangle(200, 50, 250, 100));    // 3
  8375.               ww.insert( new RWEllipse(50, 50, 100, 100));
  8376.               ww.insert( new RWText(20, 20, "Hello world, from Rogue Wave!"));
  8377.  
  8378.               ww.show(); // Show the window             // 4
  8379.               ww.update();              // Update the window
  8380.  
  8381.               MSG msg;
  8382.  
  8383.               // Enter the message loop:
  8384.               while( GetMessage( &msg, NULL, 0, 0))     // 5
  8385.               {
  8386.                 TranslateMessage( &msg );
  8387.                 DispatchMessage( &msg );
  8388.               }
  8389.               return msg.wParam;
  8390.             }
  8391.  
  8392.           Here's the line-by-line description of the program.
  8393.  
  8394.           1  This is the Windows program entry point, that every Windows
  8395.              program must have.  It is equivalent to C's "main" function.
  8396.  
  8397.           2  This creates an instance of the class DemoWindow, which we will
  8398.              see later.  It represents an abstract window into which objects
  8399.              can be "inserted".
  8400. Rogue Wave       Implementation Notes   145
  8401.  
  8402.  
  8403.  
  8404.  
  8405.  
  8406.  
  8407.  
  8408.  
  8409.                         USER'S GUIDE
  8410.  
  8411.           3  Here we insert three different objects into the DemoWindow: a
  8412.              rectangle, an ellipse, and a text string.
  8413.  
  8414.           4  This tells the DemoWindow to show itself and to update itself.
  8415.  
  8416.           5  Finally, the windows main event loop is entered.
  8417.  
  8418.             DEMOWIND.H
  8419.  
  8420.             #ifndef __DEMOWIND_H__
  8421.             #define __DEMOWIND_H__
  8422.  
  8423.             /*
  8424.              * A Demonstration Window class --- allows items that
  8425.              * inherit from the base class RWDrawable to be
  8426.              * "inserted" into it.
  8427.              */
  8428.  
  8429.             #include <slistcol.h>
  8430.             #include "shapes.h"
  8431.             #include <windows.h>
  8432.  
  8433.             class DemoWindow {
  8434.               HWND            hWnd;          // My window handle
  8435.               HANDLE               myInstance;    // My instance's handle
  8436.               int                  nCmdShow;
  8437.               RWSlistCollectables  myList; // A list of items in the window
  8438.             public:
  8439.               DemoWindow(HANDLE mom, HANDLE prev, int);
  8440.               ~DemoWindow();
  8441.  
  8442.               // Add a new item to the window:
  8443.               void            insert(RWDrawable*);
  8444.  
  8445.               HWND            handle() {return hWnd;}
  8446.               int                  registerClass();
  8447.               void            paint();
  8448.               int                  show()
  8449.                  {return ShowWindow(hWnd,nCmdShow);}
  8450.  
  8451.               void            update()  {UpdateWindow(hWnd);}
  8452.               friend long FAR PASCAL _export
  8453.                    DemoWindow_Callback(HWND, unsigned, WORD, LONG);
  8454.             };
  8455. Rogue Wave       Implementation Notes   146
  8456.  
  8457.  
  8458.  
  8459.  
  8460.  
  8461.  
  8462.  
  8463.  
  8464.                         USER'S GUIDE
  8465.  
  8466.  
  8467.             DemoWindow*  RWGetWindowPtr(HWND h);
  8468.             void    RWSetWindowPtr(HWND h, DemoWindow* p);
  8469.  
  8470.             #endif
  8471.  
  8472.           This header files declares the class DemoWindow.  A key features is
  8473.           the singly linked list called "myList" which holds the list of items
  8474.           that have been inserted into the window.  Member function
  8475.           DemoWindow::insert(RWDrawable*) allows new items to be inserted.
  8476.           Only objects that inherit from class RWDrawable, to be defined in a
  8477.           moment, may be inserted.
  8478.  
  8479.           The member function paint() may be called when it is time to repaint
  8480.           the window.  The list myList will be traversed and each item in it
  8481.           will be repainted onto the screen.
  8482.  
  8483.           Let's look at the definitions of these functions.
  8484.  
  8485.             DEMOWIND.CPP
  8486.  
  8487.             #include "demowind.h"
  8488.             #include "shapes.h"
  8489.             #include <stdlib.h>
  8490.             #include <string.h>
  8491.  
  8492.             /*
  8493.              * Construct a new window.
  8494.              */
  8495.             DemoWindow::DemoWindow(HANDLE mom, HANDLE prev, int cmdShow)   // 1
  8496.             {
  8497.               myInstance = mom;
  8498.               nCmdShow = cmdShow;
  8499.  
  8500.               // Register the class if there was no previous instance:
  8501.               if(!prev) registerClass();                              // 2
  8502.  
  8503.  
  8504.  
  8505.  
  8506.  
  8507.  
  8508.  
  8509.  
  8510. Rogue Wave       Implementation Notes   147
  8511.  
  8512.  
  8513.  
  8514.  
  8515.  
  8516.  
  8517.  
  8518.  
  8519.                         USER'S GUIDE
  8520.  
  8521.               hWnd = CreateWindow("DemoWindow",                  // 3
  8522.                     "DemoWindow",
  8523.                     WS_OVERLAPPEDWINDOW,
  8524.                     CW_USEDEFAULT, 0,
  8525.                     CW_USEDEFAULT, 0,
  8526.                     NULL,
  8527.                     NULL,
  8528.                     myInstance,
  8529.                     (LPSTR)this ); // Stash away 'this' // 4
  8530.  
  8531.               if(!hWnd) exit( FALSE );
  8532.             }
  8533.  
  8534.             /*
  8535.              * Register self. Called once only.
  8536.              */
  8537.             int
  8538.             DemoWindow::registerClass()                          // 5
  8539.             {
  8540.               WNDCLASS wndclass;
  8541.               wndclass.style = CS_HREDRAW | CS_VREDRAW;
  8542.               wndclass.lpfnWndProc      = ::DemoWindow_Callback; // 6
  8543.               wndclass.cbClsExtra       = 0;
  8544.               // Request extra space to store the 'this' pointer
  8545.               wndclass.cbWndExtra       = sizeof(this); // 7
  8546.               wndclass.hInstance        = myInstance;
  8547.               wndclass.hIcon       = 0;
  8548.               wndclass.hCursor          = LoadCursor( NULL, IDC_ARROW );
  8549.               wndclass.hbrBackground    = GetStockObject( WHITE_BRUSH );
  8550.               wndclass.lpszMenuName     = NULL;
  8551.               wndclass.lpszClassName    = "DemoWindow";
  8552.  
  8553.               if( !RegisterClass(&wndclass) ) exit(FALSE);
  8554.               return TRUE;
  8555.             }
  8556.  
  8557.             DemoWindow::~DemoWindow()
  8558.             {
  8559.               // Delete all items in my list:
  8560.               myList.clearAndDestroy();                          // 8
  8561.             }
  8562.  
  8563.  
  8564.  
  8565. Rogue Wave       Implementation Notes   148
  8566.  
  8567.  
  8568.  
  8569.  
  8570.  
  8571.  
  8572.  
  8573.  
  8574.                         USER'S GUIDE
  8575.  
  8576.             void
  8577.             DemoWindow::insert(RWDrawable* d)
  8578.             {
  8579.               // Add a new item to the window:
  8580.               myList.insert(d);                                  // 9
  8581.             }
  8582.  
  8583.             void
  8584.             DemoWindow::paint()                                  // 10
  8585.             {
  8586.               RWDrawable* shape;
  8587.               PAINTSTRUCT ps;
  8588.               BeginPaint( handle(), &ps);                             // 11
  8589.  
  8590.               // Draw all items in the list.  Start by making an iterator:
  8591.               RWSlistCollectablesIterator next(myList);// 12
  8592.  
  8593.               // Now iterate through the collection, drawing each item:
  8594.               while( shape = (RWDrawable*)next() )               // 13
  8595.                 shape->drawWith(ps.hdc);                              // 14
  8596.               EndPaint( handle(), &ps );                              // 15
  8597.             }
  8598.  
  8599.             /*
  8600.              * The callback routine for this window class.
  8601.              */
  8602.             long FAR PASCAL _export
  8603.             DemoWindow_Callback(HWND hWnd, unsigned iMessage,    // 16
  8604.                          WORD wParam, LONG lParam)
  8605.             {
  8606.               DemoWindow* pDemoWindow;
  8607.  
  8608.               if( iMessage==WM_CREATE ){                              // 17
  8609.                 // Get the "this" pointer out of the create structure
  8610.                 // and put it in the windows instance:
  8611.                 LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
  8612.                 pDemoWindow = (DemoWindow*) lpcs->lpCreateParams;
  8613.                 RWSetWindowPtr(hWnd, pDemoWindow);
  8614.                 return NULL;
  8615.               }
  8616.  
  8617.               // Get the appropriate "this" pointer
  8618.               pDemoWindow = RWGetWindowPtr(hWnd);                // 18
  8619.  
  8620. Rogue Wave       Implementation Notes   149
  8621.  
  8622.  
  8623.  
  8624.  
  8625.  
  8626.  
  8627.  
  8628.  
  8629.                         USER'S GUIDE
  8630.  
  8631.               switch( iMessage ){
  8632.                 case WM_PAINT:
  8633.                   pDemoWindow->paint();                          // 19
  8634.                   break;
  8635.                 case WM_DESTROY:
  8636.                   PostQuitMessage( 0 );
  8637.                   break;
  8638.                 default:
  8639.                   return DefWindowProc(hWnd, iMessage, wParam, lParam);
  8640.               };
  8641.               return NULL;
  8642.             }
  8643.  
  8644.             void RWSetWindowPtr(HWND h, DemoWindow* p) // 20
  8645.             {
  8646.               SetWindowLong(h, 0, (LONG)p);
  8647.             }
  8648.  
  8649.             DemoWindow* RWGetWindowPtr(HWND h)                   // 21
  8650.             {
  8651.               return (DemoWindow*)GetWindowLong(h, 0);
  8652.             }
  8653.  
  8654.           1  This is the constructor for DemoWindow.  It requires the handle
  8655.              of the application instance creating it ("mom"), the handle of
  8656.              any previously existing instance ("prev") and whether to show the
  8657.              window in iconic form.  These variables are as received from
  8658.              WinMain, the main windows procedure that we have already seen.
  8659.  
  8660.           2  The constructor checks to see if any previous application
  8661.              instance has been run and, if not, registers the class.
  8662.  
  8663.           3  The new window is created.
  8664.  
  8665.           4  A key feature is the use of the Windows "extra data" feature to
  8666.              store the "this" pointer for this DemoWindow.  The procedure to
  8667.              do this is somewhat cumbersome, but very useful.  The value
  8668.              placed here will appear in the CREATESTRUCT structure which we
  8669.              can retrieve when processing the WM_CREATE message generated by
  8670.              the CreateWindow function.
  8671.  
  8672.           5  This member function is only called for the first instance of an
  8673.              application.
  8674.  
  8675. Rogue Wave       Implementation Notes   150
  8676.  
  8677.  
  8678.  
  8679.  
  8680.  
  8681.  
  8682.  
  8683.  
  8684.                         USER'S GUIDE
  8685.  
  8686.           6  The global function DemoWindow_Callback is registered as the
  8687.              callback procedure for this window.
  8688.  
  8689.           7  We ask Windows to set aside space for the "this" pointer in this
  8690.              Windows class.  This will be used to associate a Windows handle
  8691.              with a particular DemoWindow.
  8692.  
  8693.           8  The destructor calls clearAndDestroy() to delete all items that
  8694.              have been inserted into myList.
  8695.  
  8696.           9  The member function insert(RWDrawable*) inserts a new item into
  8697.              the window.  Because (as we shall see) RWDrawable inherits from
  8698.              RWCollectable, there is no need to do a cast when calling
  8699.              RWSlistCollectables::insert(RWCollectable*).  By making myList
  8700.              private and offering a restricted insert that takes arguments of
  8701.              type RWDrawable* only, we insure that only "drawables" will be
  8702.              inserted into the window.
  8703.  
  8704.           10 Here's the paint procedure, called when it is time to repaint the
  8705.              window.
  8706.  
  8707.           11 We start by getting the handle for this window, and then calling
  8708.              BeginPaint to fill a PAINTSTRUCT with information about the
  8709.              painting.
  8710.  
  8711.           12 An iterator is constructed in preparation for traversing the list
  8712.              of items to be painted.
  8713.  
  8714.           13 Get the next item to be painted.  If nil is returned then there
  8715.              are no more items and the while loop will finish.
  8716.  
  8717.           14 For each item, call the virtual function drawWith, causing the
  8718.              item to paint itself onto the given device context.
  8719.  
  8720.           15 The PAINTSTRUCT is returned.
  8721.  
  8722.           16 Here's the callback routine to be called when it is necessary to
  8723.              process a message for this window.  It uses Borland C++'s very
  8724.              convenient "_export" keyword to indicate that this function
  8725.              should be exported.  If you do this, there is no need to list the
  8726.              function in an "Exports" section of the module definition file.
  8727.  
  8728.           17 If the message is a WM_CREATE message then it was generated by
  8729.              the CreateWindow function and this is the first time through for
  8730. Rogue Wave       Implementation Notes   151
  8731.  
  8732.  
  8733.  
  8734.  
  8735.  
  8736.  
  8737.  
  8738.  
  8739.                         USER'S GUIDE
  8740.  
  8741.              this procedure.  Use the rather baroque procedure to fetch the
  8742.              "this" pointer from the CREATESTRUCT (recall, it was inserted at
  8743.              line 4) and put it into the Windows extra data.  The function
  8744.              RWSetWindowPtr will be defined later.
  8745.  
  8746.           18 The function RWGetWindowPtr(HWND) is used to retrieve the pointer
  8747.              to the appropriate DemoWindow, given a Windows HANDLE.
  8748.  
  8749.           19 If a WM_PAINT has been retrieved, then call the paint() member
  8750.              function, which we have already seen.
  8751.  
  8752.           20 This function is used to put a "this" pointer into the Windows
  8753.              extra data.  The idea is to have a one-to-one mapping of Windows
  8754.              handles to instances of DemoWindow.
  8755.  
  8756.           21 This function is used to fetch the "this" pointer back out.
  8757.  
  8758.           Finally, we have the subclasses of RWDrawable.  Only one has been
  8759.           reprinted here: RWRectangle.
  8760.  
  8761.             SHAPES.H (excerpt)
  8762.  
  8763.             class RWDrawable : public RWCollectable {
  8764.             public:
  8765.               virtual void    drawWith(HDC) const = 0;
  8766.             };
  8767.  
  8768.             class RWRectangle : public RWDrawable {
  8769.               RECT       bounds;   // The bounds of the rectangle
  8770.             public:
  8771.               RWRectangle() { }
  8772.               RWRectangle(int, int, int, int);
  8773.  
  8774.               // Inherited from RWDrawable:
  8775.               virtual void              drawWith(HDC) const;
  8776.  
  8777.               // Inherited from RWCollectable:
  8778.               virtual unsigned          binaryStoreSize() const
  8779.                 {return 4*sizeof(int);}
  8780.               virtual unsigned          hash() const;
  8781.               virtual ClassID           isA() const {return 0x1000;}
  8782.               virtual RWBoolean         isEqual(const RWCollectable*) const;
  8783.               virtual RWCollectable*         newSpecies() const;
  8784.               virtual void              restoreGuts(RWvistream& s);
  8785. Rogue Wave       Implementation Notes   152
  8786.  
  8787.  
  8788.  
  8789.  
  8790.  
  8791.  
  8792.  
  8793.  
  8794.                         USER'S GUIDE
  8795.  
  8796.               virtual void              restoreGuts(RWFile&);
  8797.               virtual void              saveGuts(RWvostream& s) const;
  8798.               virtual void              saveGuts(RWFile&) const;
  8799.             };
  8800.  
  8801.           Class RWDrawable is an abstract base class that inherits from the
  8802.           Tools.h++ class RWCollectable and adds a new member function
  8803.           drawWith(HDC).  Subclasses specializing RWDrawable should implement
  8804.           this function to draw itself onto the supplied device context handle.
  8805.  
  8806.           Class RWRectangle inherits from RWDrawable.  Note that it just uses
  8807.           the Windows-provided struct RECT as member data to hold the corners
  8808.           of the rectangle.  For the purposes of this DLL demo, it really isn't
  8809.           necessary to provide definitions for any of the member functions
  8810.           inherited from RWCollectable but, for the sake of completeness, let's
  8811.           do it anyway.
  8812.  
  8813.             SHAPES.CPP (excerpt)
  8814.  
  8815.             #include "shapes.h"
  8816.             #include <vstream.h>
  8817.             #include <rwfile.h>
  8818.  
  8819.             DEFINE_COLLECTABLE(RWRectangle)                           // 1
  8820.  
  8821.             // Constructor
  8822.             RWRectangle::RWRectangle(int l, int t, int r, int b) // 2
  8823.             {
  8824.               bounds.left   = l;
  8825.               bounds.top    = t;
  8826.               bounds.right  = r;
  8827.               bounds.bottom = b;
  8828.             }
  8829.  
  8830.             // Inherited from Drawable:
  8831.             void
  8832.             RWRectangle::drawWith(HDC hdc) const                 // 3
  8833.             {
  8834.               // Make the Windows call:
  8835.               Rectangle(hdc, bounds.left, bounds.top,
  8836.                     bounds.right, bounds.bottom);
  8837.             }
  8838.  
  8839.  
  8840. Rogue Wave       Implementation Notes   153
  8841.  
  8842.  
  8843.  
  8844.  
  8845.  
  8846.  
  8847.  
  8848.  
  8849.                         USER'S GUIDE
  8850.  
  8851.             // Inherited from RWCollectable:
  8852.             unsigned
  8853.             RWRectangle::hash() const                            // 4
  8854.             {
  8855.               return bounds.left ^ bounds.top ^ bounds.bottom ^ bounds.right;
  8856.             }
  8857.  
  8858.             RWBoolean
  8859.             RWRectangle::isEqual(const RWCollectable* c) const   // 5
  8860.             {
  8861.               if(c->isA() != isA() ) return FALSE;
  8862.  
  8863.               const RWRectangle* r = (const RWRectangle*)c;
  8864.  
  8865.               return     bounds.left   == r->bounds.left  &&
  8866.                     bounds.top    == r->bounds.top   &&
  8867.                     bounds.right  == r->bounds.right &&
  8868.                     bounds.bottom == r->bounds.bottom;
  8869.             }
  8870.  
  8871.             // Restore the RWRectangle from a virtual stream:
  8872.             void
  8873.             RWRectangle::restoreGuts(RWvistream& s)     // 6
  8874.             {
  8875.               s >> bounds.left  >> bounds.top;
  8876.               s >> bounds.right >> bounds.bottom;
  8877.             }
  8878.  
  8879.             // Restore from a RWFile:
  8880.             void
  8881.             RWRectangle::restoreGuts(RWFile& f)                  // 7
  8882.             {
  8883.               f.Read(bounds.left);
  8884.               f.Read(bounds.top);
  8885.               f.Read(bounds.right);
  8886.               f.Read(bounds.bottom);
  8887.             }
  8888.  
  8889.             void
  8890.             RWRectangle::saveGuts(RWvostream& s) const  // 8
  8891.             {
  8892.               s << bounds.left  << bounds.top;
  8893.               s << bounds.right << bounds.bottom;
  8894.             }
  8895. Rogue Wave       Implementation Notes   154
  8896.  
  8897.  
  8898.  
  8899.  
  8900.  
  8901.  
  8902.  
  8903.  
  8904.                         USER'S GUIDE
  8905.  
  8906.  
  8907.             void
  8908.             RWRectangle::saveGuts(RWFile& f) const               // 9
  8909.             {
  8910.               f.Write(bounds.left);
  8911.               f.Write(bounds.top);
  8912.               f.Write(bounds.right);
  8913.               f.Write(bounds.bottom);
  8914.             }
  8915.  
  8916.           1  This is a macro that all subclasses of RWCollectable are required
  8917.              to compile once, and only once.  See Section 15.10.11 for more
  8918.              details.
  8919.           2  The constructor for RWRectangle.  It fills in the RECT structure.
  8920.           3  This is the definition of the virtual function drawWith(HDC).  It
  8921.              simply makes a call to the Windows function "Rectangle()" with
  8922.              appropriate arguments.
  8923.           4  Supplies an appropriate hashing value in case we ever want to
  8924.              retrieve this RWRectangle from a hash table.
  8925.           5  Supplies an appropriate isEqual() implementation.
  8926.           6  This function retrieves the RWRectangle from a virtual stream.
  8927.           7  This function retrieves the RWRectangle from a RWFile.
  8928.           8  This function stores the RWRectangle on a virtual stream.  Note
  8929.              how there is no need to separate elements by white space -- this
  8930.              will be done by the virtual stream, if necessary.
  8931.           9  This function stores the RWRectangle on a RWFile.
  8932.           The other shapes (RWEllipse and RWText) are implemented in a similar
  8933.           manner.
  8934.  
  8935.  
  8936.  
  8937.  
  8938.  
  8939.  
  8940.  
  8941.  
  8942.  
  8943.  
  8944.  
  8945.  
  8946.  
  8947.  
  8948.  
  8949.  
  8950. Rogue Wave       Implementation Notes   155
  8951.  
  8952.  
  8953.  
  8954.  
  8955.  
  8956.  
  8957.  
  8958.  
  8959.  
  8960.  
  8961.  
  8962.  
  8963.  
  8964.  
  8965.  
  8966.                                                           S e c t i o n    1 7 
  8967.  
  8968.  
  8969.                                                                        Examples
  8970.  
  8971.  
  8972.  
  8973.           In this section we outline several examples that use the Rogue Wave
  8974.           Tools.h++ classes.  The source code for these examples is included in
  8975.           the subdirectory toolexam.  Sample input and output files, if needed,
  8976.           as well as makefiles are also included in the subdirectory.
  8977.  
  8978.  
  8979. 17.1 Example 1:     The RWTime and RWDate classes
  8980.  
  8981.  
  8982.  
  8983.           This example illustrates the use of the RWTime and RWDate classes.  A
  8984.           RWDate is constructed with today's date, then printed with a variety
  8985.           of formats.  A RWTime is constructed, then converted to a RWDate.
  8986.           Examples of the use of member functions to return information about
  8987.           RWDates and RWTimes are also given.
  8988.  
  8989.  
  8990. 17.2 Example 2:     The RWString class
  8991.  
  8992.  
  8993.  
  8994.           This example illustrates the use of the RWString and RWSubString
  8995.           classes.  Representative member functions for the classes are
  8996.           illustrated, including constructors, concatenation and appending,
  8997.           pattern matching, converting to upper case, and input/output of
  8998.           strings.  An example of using a RWSubString as an lvalue is given.
  8999.  
  9000.  
  9001.  
  9002.  
  9003.  
  9004.  
  9005. Rogue Wave             Examples   157
  9006.  
  9007.  
  9008.  
  9009.  
  9010.  
  9011.  
  9012.  
  9013.  
  9014.                         USER'S GUIDE
  9015.  
  9016.  
  9017. 17.3 Example 3:     GDlist - A class for generic doubly-linked lists
  9018.  
  9019.  
  9020.  
  9021.           This example illustrates the use of the "generic collection classes",
  9022.           with a doubly-linked list of ints.  The macro
  9023.  
  9024.             declare(GDlist, int)
  9025.  
  9026.           declares a doubly-linked list of ints with class name GDlist(int).
  9027.           The constructor for an instance of a GDlist(int) with name L and no
  9028.           entries is:
  9029.  
  9030.             GDlist(int) L;
  9031.  
  9032.           Commands to insert and append ints to a linked-list are illustrated,
  9033.           as are commands to remove and print each entry.
  9034.  
  9035.           An iterator c for the linked-list is constructed with the statement:
  9036.  
  9037.             GDlistIterator(int) c(L);
  9038.  
  9039.           The iterator is exercised in various ways, to move around in the
  9040.           list, to search for and remove entries, and finally, to move through
  9041.           the list and print each entry.
  9042.  
  9043.  
  9044. 17.4 Example 4:     RWBinaryTree - A sorted collection of RWCollectableStrings
  9045.  
  9046.  
  9047.  
  9048.           This example uses class RWBinaryTree to store and retrieve
  9049.           collectable strings in a binary tree.  The header file "collstr.h"
  9050.           contains the declarations for class RWCollectableString, which
  9051.           inherits class RWString and class RWCollectable.  Most of the
  9052.           functionality of class RWCollectableString comes from class RWString.
  9053.           The virtual function compareTo(), which is inherited from class
  9054.           RWCollectable, has been redefined by RWCollectableString to compare
  9055.           strings lexicographically, and is used to sort the strings in the
  9056.           binary tree.  The virtual function isEqual() has also been inherited
  9057.           from class RWCollectable, and is redefined to imply equality of
  9058.           strings.
  9059.  
  9060. Rogue Wave             Examples   158
  9061.  
  9062.  
  9063.  
  9064.  
  9065.  
  9066.  
  9067.  
  9068.  
  9069.                         USER'S GUIDE
  9070.  
  9071.           A binary tree is first constructed with no entries:
  9072.  
  9073.             RWBinaryTree B;
  9074.  
  9075.           Then an input file "textfile.in" containing a group of words is
  9076.           opened, and the words are inserted into the tree.  A loop to do
  9077.           various things to the tree is set up, with options:
  9078.  
  9079.             (i)nsert (s)earch (d)elete (l)ist e(x)it:
  9080.  
  9081.           These options enable you to insert new strings, search for strings,
  9082.           delete strings, list all the contents of the tree in order, and
  9083.           finally, to exit.  These options exercise many of the member
  9084.           functions of the class RWBinaryTree.
  9085.  
  9086.           In order to list the contents of the binary tree, the member function
  9087.           apply() is used, which takes a pointer to a user-defined global
  9088.           function of the form:
  9089.  
  9090.             void yourApplyFunction(RWCollectable*, void*);
  9091.  
  9092.           and calls it for every member of the tree, in order.  In the example,
  9093.           we use such a function to print each member of the tree:
  9094.  
  9095.            static void printStrings(RWCollectable* c, void*)
  9096.            {
  9097.                 cout << * (RWCollectableString*) c ;
  9098.            }
  9099.  
  9100.            main()
  9101.            {
  9102.                 RWBinaryTree B;
  9103.                 .
  9104.                 .
  9105.                 .
  9106.                 B.apply(printStrings, nil); // Traverse tree, printing members
  9107.                 .
  9108.                 .
  9109.                 .
  9110.            }
  9111.  
  9112.           The cast in printStrings() is required.  This is because the function
  9113.           takes an argument of type RWCollectable*, i.e., a pointer to the base
  9114.           class.  In order to print the item it points to, it must first be
  9115. Rogue Wave             Examples   159
  9116.  
  9117.  
  9118.  
  9119.  
  9120.  
  9121.  
  9122.  
  9123.  
  9124.                         USER'S GUIDE
  9125.  
  9126.           cast into its real identity, a pointer to a RWCollectableString, and
  9127.           then dereferenced.  The result, which is a RWCollectableString,
  9128.           inherits its ability to print from class RWString.
  9129.  
  9130.  
  9131.  
  9132.  
  9133.  
  9134.  
  9135.  
  9136.  
  9137.  
  9138.  
  9139.  
  9140.  
  9141.  
  9142.  
  9143.  
  9144.  
  9145.  
  9146.  
  9147.  
  9148.  
  9149.  
  9150.  
  9151.  
  9152.  
  9153.  
  9154.  
  9155.  
  9156.  
  9157.  
  9158.  
  9159.  
  9160.  
  9161.  
  9162.  
  9163.  
  9164.  
  9165.  
  9166.  
  9167.  
  9168.  
  9169.  
  9170. Rogue Wave             Examples   160
  9171.  
  9172.  
  9173.  
  9174.  
  9175.  
  9176.  
  9177.  
  9178.  
  9179.                         USER'S GUIDE
  9180.  
  9181.  
  9182. 17.5 Example 5:     RWHashDictionary - A dictionary of keys and values
  9183.  
  9184.  
  9185.  
  9186.           This example is similar to the previous example and illustrates the
  9187.           use of the Dictionary collection class RWHashDictionary, which stores
  9188.           and retrieves key-value pairs, and which is implemented as a hash
  9189.           table.  This example uses RWCollectableStrings as keys and
  9190.           RWCollectableInts as values.
  9191.  
  9192.           Since a hash table is used here, the virtual function hash() is being
  9193.           used to find the proper keys.
  9194.  
  9195.           A loop to perform various operations on the dictionary is set up,
  9196.           much as in the previous example.  Here, however, keys and values are
  9197.           inserted, and a key is used to search for a value.  The member
  9198.           function apply() for this class takes a pointer to a function of the
  9199.           form
  9200.  
  9201.            void
  9202.            anotherApplyFunction(RWCollectable* key,RWCollectable* value,
  9203.            void*);
  9204.  
  9205.           This function operates on both the key and the value (but should not
  9206.           alter the key).
  9207.  
  9208.  
  9209. 17.6 Example 6:     RWBTreeOnDisk - A B-Tree of keys and values, stored on disk
  9210.  
  9211.  
  9212.  
  9213.           This example exercises the class RWBTreeOnDisk, which maintains a
  9214.           Dictionary of  key-value pairs on a disk file, where the keys are
  9215.           arrays of chars and the values are set by the typedef storedValue,
  9216.           typically a long int.  The values may represent anything, but
  9217.           typically will represent offsets to objects that are stored on disk.
  9218.  
  9219.           A RWFileManager must be constructed first with the name of the disk
  9220.           file:
  9221.  
  9222.             RWFileManager fm(filename);
  9223.  
  9224.           The RWFileManager controls allocation, deallocation and coalescence
  9225. Rogue Wave             Examples   161
  9226.  
  9227.  
  9228.  
  9229.  
  9230.  
  9231.  
  9232.  
  9233.  
  9234.                         USER'S GUIDE
  9235.  
  9236.           of free space on the disk file.  After the RWFileManager has been
  9237.           constructed, it may be used to allocate space for the objects.
  9238.  
  9239.           The RWBTreeOnDisk is constructed from a RWFileManager:
  9240.  
  9241.             RWBTreeOnDisk B(fm);
  9242.  
  9243.           If the B-Tree is constructed from an old file, the old root node is
  9244.           read into memory; if it is constructed from a new file, a new B-Tree,
  9245.           with no entries, is constructed and written to disk.  A file
  9246.           "example6.dat" contains a sample B-Tree with a number of entries.
  9247.  
  9248.           A loop does various things to the tree, as in the above examples.
  9249.           However, in this case, the changes are  updated continuously on the
  9250.           disk file so that you can quit, then restart with the same filename.
  9251.  
  9252.  
  9253. 17.7 Example7 & 8:  Class RWFileManager
  9254.  
  9255.  
  9256.  
  9257.           These examples are described in Section 11.2." \t """ \t ""
  9258.  
  9259.  
  9260.  
  9261.  
  9262.  
  9263.  
  9264.  
  9265.  
  9266.  
  9267.  
  9268.  
  9269.  
  9270.  
  9271.  
  9272.  
  9273.  
  9274.  
  9275.  
  9276.  
  9277.  
  9278.  
  9279.  
  9280. Rogue Wave             Examples   162