/*
 * "Bus" example from the Tools.h++ manual.
 *
 * $Id: bus.cpp,v 2.7 1994/01/13 07:51:31 jims Exp $
 *
 ****************************************************************************
 *
 * Rogue Wave Software, Inc.
 * P.O. Box 2328
 * Corvallis, OR 97339
 * Voice: (503) 754-3010	FAX: (503) 757-6650
 *
 * Copyright (C) 1989 - 1993.
 * This software is subject to copyright protection under the laws of
 * the United States and other countries.
 *
 ***************************************************************************
 *
 * $Log: bus.cpp,v $
 * 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();

  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
{
  f.Write(busNumber_);
  f << driver_ << customers_;

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

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

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

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

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

void
Bus::restoreGuts(RWvistream& 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)
{
  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;
}

