/*
 * Example 4: class BinaryTree, storing and retrieving collectable strings
 *
 * $Id: bintree.cpp,v 7.4 1996/03/25 23:10:40 pearson Exp $
 *
 * (c) Copyright 1989 - 1996 Rogue Wave Software, Inc.
 * ALL RIGHTS RESERVED
 *
 * The software and information contained herein are proprietary to, and
 * comprise valuable trade secrets of, Rogue Wave Software, Inc., which
 * intends to preserve as trade secrets such software and information.
 * This software is furnished pursuant to a written license agreement and
 * may be used, copied, transmitted, and stored only in accordance with
 * the terms of such license and with the inclusion of the above copyright
 * notice.  This software and information or any other copies thereof may
 * not be provided or otherwise made available to any other person.
 *
 * Notwithstanding any other lease or license that may pertain to, or
 * accompany the delivery of, this computer software and information, the
 * rights of the Government regarding its use, reproduction and disclosure
 * are as set forth in Section 52.227-19 of the FARS Computer
 * Software-Restricted Rights clause.
 * 
 * Use, duplication, or disclosure by the Government is subject to
 * restrictions as set forth in subparagraph (c)(1)(ii) of the Rights in
 * Technical Data and Computer Software clause at DFARS 252.227-7013.
 * Contractor/Manufacturer is Rogue Wave Software, Inc.,
 * P.O. Box 2328, Corvallis, Oregon 97339.
 *
 * This computer software and information is distributed with "restricted
 * rights."  Use, duplication or disclosure is subject to restrictions as
 * set forth in NASA FAR SUP 18-52.227-79 (April 1985) "Commercial
 * Computer Software-Restricted Rights (April 1985)."  If the Clause at
 * 18-52.227-74 "Rights in Data General" is specified in the contract,
 * then the "Alternate III" clause applies.
 *
 ***************************************************************************
 *
 * $Log: bintree.cpp,v $
 * Revision 7.4  1996/03/25 23:10:40  pearson
 * Fix eof problem for Macintosh
 *
 * Revision 7.3  1995/10/26 17:30:33  pearson
 * Remove .hpp includes for Zortech compiler
 *
 * Revision 7.2  1995/09/06  21:29:41  jims
 * Use new copyright macro and rename file from example4.cpp to bintree.cpp
 *
 * Revision 7.1  1994/10/16  04:14:31  josh
 * Merged 6.1 and 7.0 development trees
 *
 * Revision 6.4  1994/07/12  20:40:30  vriezen
 * Updated Copyright
 *
 * Revision 6.3  1994/06/02  21:02:08  foote
 * Added RW_END_PROMPT macro
 *
 * Revision 6.2  1994/06/02  19:24:05  foote
 * Port to Symantec 7.0 on Macintosh
 *
 * Revision 6.1  1994/04/15  19:08:27  vriezen
 * Move all files to 6.1
 *
 * Revision 2.2  1993/10/19  14:35:26  griswolf
 * flush cout (cin not tied to cout for some compilers)
 *
 * Revision 2.1  1992/12/04  05:07:27  myersn
 * update for tools.h++ 6.0
 *
 * Revision 2.0  1992/10/23  03:34:26  keffer
 * RCS Baseline version
 *
 * 
 *    Rev 1.1   07 Jun 1992 17:11:08   KEFFER
 * Tools.h++ V5.1
 * 
 */


// Declarations for Binary Tree class:
#include "rw/bintree.h"

/*
 * Declarations for class RWCollectableString.  
 * This class inherits class RWCString and class RWCollectable.  
 * Class RWCollectable has a virtual function compareTo() that is redefined 
 * by class RWCollectableString.  This function is used to order the 
 * RWCollectableStrings in the binary tree.
 */
#include "rw/collstr.h"
#include "rw/rstream.h"

/*
 * "STARTWRAP" and "ENDWRAP" are macros that allow inclusion of ANSI-C header
 * files using standard "C" linkage.  They are necessary for C++ compilers that
 * do not supply their own special "C++" header files and, instead, rely on
 * standard C header files.
 */
STARTWRAP
#include <stdlib.h>
ENDWRAP

/*
 * The following complex conditional inclusion owes its existence to
 * everyone going their own way, defining "standard" include files.
 */

#  ifdef __GLOCK__
#    include <fstream.hxx>
#  else
#    include <fstream.h>
#  endif

#ifdef applec                          
#  define RW_END_PROMPT   endl << flush
#else                                  
#  define RW_END_PROMPT   flush         
#endif                                 

/*
 * A pointer to this function will be handed to RWBinaryTree::apply() 
 * to enumerate the members of the collection.
 */
static void
printStrings(RWCollectable* c, void*)
{
  /*
   * Cast the RWCollectable pointer to a RWCollectableString pointer,
   * then dereference and print.  RWCollectableString inherits
   * its ability to be printed from its base class RWCString.
   */
  cout << * (RWCollectableString*) c << " ";
}


main()
{
  RWBinaryTree		B;
  RWCollectableString	aWord;
  RWCollectableString*	pWord;
  int i = 0;

  cout << "***** Example using a Binary Tree (SortedCollection) ******\n";
  
  ifstream inputFile("textfile.in", ios::in);
  if(!inputFile){
    cerr << "Cannot open file textfile.in.\n";
    exit(1);
  }

  cout << "Reading from file \"textfile.in\"...\n";

  // Read until we hit an EOF:
  // Macintosh needs explicit check for eof 

#ifndef macintosh
  while ( inputFile >> aWord ) {
#else
  while ( !(inputFile >> aWord ).eof() ) { 
#endif  

    // Transfer it to something off the heap and insert:
    pWord = new RWCollectableString(aWord);
    B.insert(pWord);

    cout << i++ << " " << *pWord << endl;
  }

  cout << "done.\n\nA total of " << i << " words were read.\n";
  cout << "Contents of the tree are:\n\n";
  B.apply(printStrings, 0);    // Uses global function defined above.
  cout << "\n\n";

  // Loop to do various things to the table:
  char option;
  
  while(1){

    cout << "(i)nsert (s)earch (d)elete (c)lear (l)ist e(x)it:\t" << RW_END_PROMPT;

    // Check for EOF or terminating character:
    if ( !(cin >> option).good() || option=='x' || option=='X' ) break;

    switch ( option ) {
    case 'i':		// Insert a word in tree.
    case 'I':
      cout << "Enter word:\t" << RW_END_PROMPT;
      pWord = new RWCollectableString;
      if(pWord){
        if( (cin >> *pWord).good() ) B.insert(pWord);	// Check for failed stream
        else delete pWord;
      }
      else cerr << "Out of memory.\n";
      break;
    case 's':		// Find the number of occurrences of a word.
    case 'S':
      cout << "Enter word:\t" << RW_END_PROMPT;
      cin >> aWord;
      cout << B.occurrencesOf(&aWord) << " occurrences of word in tree.\n";
      break;
    case 'd':   	// Remove a word.
    case 'D':
      cout << "Enter word:\t" << RW_END_PROMPT;
      cin >> aWord;
      B.removeAndDestroy(&aWord);
      break;
    case 'c':
    case 'C':		// Both clear AND destroy the contents
      B.clearAndDestroy();
      break;
    case 'l':
    case 'L':		// List the contents of the tree, in order.
      cout << B.entries() << " entries in tree:\n";
      B.apply(printStrings,0);
      cout << "\n\n";
      break;
    default:
      cerr << "Unrecognized.\n";
    } 	// End switch
  }	// End while

  cout << endl;		// To pretty things up.

  B.clearAndDestroy();	// Not really essential, but good style

  return 0;
}
