/*
 * "Bus" example from the Tools.h++ manual.
 *
 * $Id: bus.cpp,v 7.4 1996/02/18 23:34:16 kyle 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: bus.cpp,v $
 * Revision 7.4  1996/02/18 23:34:16  kyle
 * Millenium adds prototype for restoreBus
 *
 * Revision 7.3  1995/09/06 21:30:56  jims
 * Use new copyright macro
 *
 * Revision 7.2  1995/06/30  15:15:52  griswolf
 * Scopus 788: Correct the store size if passengers_ is nil.
 *
 * Revision 7.1  1994/10/16  04:14:18  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/29  16:07:58  vriezen
 * Call RWCollectable::saveGuts and restoreGuts in overloaded code.
 *
 * Revision 6.2  1994/06/02  19:15:01  foote
 * Port to Symantec 7.0 on Macintosh
 *
 * Revision 6.1  1994/04/15  19:08:17  vriezen
 * Move all files to 6.1
 *
 * Revision 2.7  1994/01/13  07:51:31  jims
 * Add restore from portable ascii stream
 *
 * Revision 2.6  1993/06/21  17:58:18  keffer
 * Added RCS ident.
 *
 *
 */

#include "bus.h"
#include "rw/bstream.h"
#include "rw/pstream.h"
#include "rw/rwfile.h"
#ifdef __ZTC__
# include <fstream.hpp>
#else
# ifdef __GLOCK__
#   include <fstream.hxx>
# else
#   include <fstream.h>
# endif
#endif

RWDEFINE_COLLECTABLE(Bus, 200)

Bus::Bus() :
  busNumber_  (0),
  driver_     ("Unknown"),
  passengers_ (rwnil)
{
}

Bus::Bus(int busno, const RWCString& driver) :
  busNumber_  (busno),
  driver_     (driver),
  passengers_ (rwnil)
{
}

Bus::~Bus()
{
  customers_.clearAndDestroy();
  delete passengers_;
}

RWspace
Bus::binaryStoreSize() const
{
  RWspace count = customers_.recursiveStoreSize() +
    sizeof(busNumber_) +
    driver_.binaryStoreSize();

  if (passengers_)
    count += passengers_->recursiveStoreSize();
  else
    count += RWCollectable::nilStoreSize();

  return count;
}

int
Bus::compareTo(const RWCollectable* c) const
{
  const Bus* b = (const Bus*)c;
  if (busNumber_ == b->busNumber_) return 0;
  return busNumber_ > b->busNumber_ ? 1 : -1;
}

RWBoolean
Bus::isEqual(const RWCollectable* c) const
{
  const Bus* b = (const Bus*)c;
  return busNumber_ == b->busNumber_;
}

unsigned
Bus::hash() const
{
  return (unsigned)busNumber_;
}

size_t
Bus::customers() const
{
  return customers_.entries();
}

size_t
Bus::passengers() const
{
  return passengers_ ? passengers_->entries() : 0;
}

void
Bus::saveGuts(RWFile& f) const
{
  RWCollectable::saveGuts(f);
  f.Write(busNumber_);
  f << driver_ << customers_;

  if (passengers_)
    f << passengers_;
  else
    f << RWnilCollectable;
}

void
Bus::saveGuts(RWvostream& strm) const
{
  RWCollectable::saveGuts(strm);
  strm << busNumber_ << driver_ << customers_;

  if (passengers_)
    strm << passengers_;
  else
    strm << RWnilCollectable;
}

void
Bus::restoreGuts(RWFile& f)
{
  RWCollectable::restoreGuts(f);
  f.Read(busNumber_);
  f >> driver_ >> customers_;

  delete passengers_;
  f >> passengers_;
  if (passengers_ == RWnilCollectable)
    passengers_ = rwnil;
}

void
Bus::restoreGuts(RWvistream& strm)
{
  RWCollectable::restoreGuts(strm);
  strm >> busNumber_ >> driver_ >> customers_;

  delete passengers_;
  strm >> passengers_;
  if (passengers_ == RWnilCollectable)
    passengers_ = rwnil;
}


void
Bus::addPassenger(const char* name)
{
  RWCollectableString* s = new RWCollectableString(name);
  customers_.insert( s );

  if (!passengers_)
    passengers_ = new RWSet;

  passengers_->insert(s);
}

void
Bus::addCustomer(const char* name)
{
  customers_.insert( new RWCollectableString(name) );
}

void restoreBus(RWvistream& stream); // prototype
void restoreBus(RWvistream& stream)
{
  Bus* newBus;
  stream >> newBus;		// Restore a bus

  cout << "Bus number " << newBus->number() 
    << " has been restored; its driver is " << newBus->driver() << ".\n";
  cout << "It has " << newBus->customers() << " customers and "
    << newBus->passengers() << " passengers.\n\n";

  delete newBus;
}

main()
{
  Bus theBus(1, "Kesey");
  theBus.addPassenger("Frank");
  theBus.addPassenger("Paula");
  theBus.addCustomer("Dan");
  theBus.addCustomer("Chris");

  {
    ofstream f("bus.bin");
    RWbostream stream(f);
    stream << theBus;		// Persist theBus to a binary stream
  }

  {
    ofstream f("bus.str");
    RWpostream stream(f);
    stream << theBus;		// Persist theBus to an ASCII stream
  }


  {
    ifstream f("bus.bin");
    RWbistream stream(f);
    cout << "Restoring from a binary stream...\n";
    restoreBus(stream);		// Restore from a binary stream
  }

  {
    ifstream f("bus.str");
    RWpistream stream(f);
    cout << "Restoring from an ASCII stream...\n";
    restoreBus(stream);		// Restore from an ASCII stream
  }

  // The following line should not be necessary, but a bug in Sun C++
  // requires it:
  cout.flush();

  return 0;
}

