//===========================================================================
// @(#) $Name: arts++-1-1-a12 $
// @(#) $Id: Arts.cc,v 1.3 2004/04/21 23:51:30 kkeys Exp $
//===========================================================================
//  Copyright Notice
//
//  By accessing this software, arts++, you are duly informed
//  of and agree to be bound by the conditions described below in this
//  notice:
//
//  This software product, arts++, is developed by Daniel W. McRobb, and
//  copyrighted(C) 1998 by the University of California, San Diego
//  (UCSD), with all rights reserved.  UCSD administers the CAIDA grant,
//  NCR-9711092, under which part of this code was developed.
//
//  There is no charge for arts++ software.  You can redistribute it
//  and/or modify it under the terms of the GNU Lesser General Public
//  License, Version 2.1, February 1999, which is incorporated by
//  reference herein.
//
//  arts++ is distributed WITHOUT ANY WARRANTY, IMPLIED OR EXPRESS, OF
//  MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE or that the use
//  of it will not infringe on any third party's intellectual
//  property rights.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with arts++.  Copies can also be obtained from:
//
//    http://www.gnu.org/copyleft/lesser.html
//
//  or by writing to:
//
//  Free Software Foundation, Inc.
//  59 Temple Place, Suite 330
//  Boston, MA 02111-1307
//  USA
//
//  Or contact:
//
//    info@caida.org
//===========================================================================

extern "C" {
#include <stdio.h>
}

#include <string>
#include <map>

#include "Arts.hh"

using namespace std;

static const std::string rcsid = "@(#) $Name: arts++-1-1-a12 $ $Id: Arts.cc,v 1.3 2004/04/21 23:51:30 kkeys Exp $";

//------------------------------------------------------------------------
//                            Arts::Arts()
//........................................................................
//  constructor
//------------------------------------------------------------------------
Arts::Arts()
{
  this->_data._ipPath = (ArtsIpPathData *)0;
  this->_data._asMatrix = (ArtsAsMatrixData *)0;
  this->_data._netMatrix = (ArtsNetMatrixData *)0;
  this->_data._portTable = (ArtsPortTableData *)0;
  this->_data._portMatrix = (ArtsPortMatrixData *)0;
  this->_data._protocolTable = (ArtsProtocolTableData *)0;
  this->_data._selectedPortTable = (ArtsSelectedPortTableData *)0;
  this->_data._interfaceMatrix = (ArtsInterfaceMatrixData *)0;
  this->_data._nextHopTable = (ArtsNextHopTableData *)0;
  this->_data._bgp4RouteTable = (ArtsBgp4RouteTableData *)0;
  this->_data._rttTimeSeriesTable = (ArtsRttTimeSeriesTableData *)0;
  this->_data._tosTable = (ArtsTosTableData *)0;
  
  #ifndef NDEBUG
    ++_numObjects;
  #endif
}

//----------------------------------------------------------------------------
//                      Arts::Arts(const Arts & arts) 
//............................................................................
//  
//----------------------------------------------------------------------------
Arts::Arts(const Arts & arts)
{
  this->_header = arts.Header();
  this->_attributes = arts.Attributes();

  switch (this->_header.Identifier()) {
    case artsC_OBJECT_IP_PATH:
      this->_data._ipPath = new ArtsIpPathData;
      assert(this->_data._ipPath != (ArtsIpPathData *)0);
      *(this->_data._ipPath) = *(arts.IpPathData());
      break;
      
    case artsC_OBJECT_AS_MATRIX:
      this->_data._asMatrix = new ArtsAsMatrixData;
      assert(this->_data._asMatrix != (ArtsAsMatrixData *)0);
      *(this->_data._asMatrix) = *(arts.AsMatrixData());
      break;

    case artsC_OBJECT_NET:
      this->_data._netMatrix = new ArtsNetMatrixData;
      assert(this->_data._netMatrix != (ArtsNetMatrixData *)0);
      *(this->_data._netMatrix) = *(arts.NetMatrixData());
      break;

    case artsC_OBJECT_PORT:
      this->_data._portTable = new ArtsPortTableData;
      assert(this->_data._portTable != (ArtsPortTableData *)0);
      *(this->_data._portTable) = *(arts.PortTableData());
      break;

    case artsC_OBJECT_SELECTED_PORT:
      this->_data._selectedPortTable = new ArtsSelectedPortTableData;
      assert(this->_data._selectedPortTable != (ArtsSelectedPortTableData *)0);
      *(this->_data._selectedPortTable) = *(arts.SelectedPortTableData());
      break;
      
    case artsC_OBJECT_PORT_MATRIX:
      this->_data._portMatrix = new ArtsPortMatrixData;
      assert(this->_data._portMatrix != (ArtsPortMatrixData *)0);
      *(this->_data._portMatrix) = *(arts.PortMatrixData());
      break;

    case artsC_OBJECT_PROTO:
      this->_data._protocolTable = new ArtsProtocolTableData;
      assert(this->_data._protocolTable != (ArtsProtocolTableData *)0);
      *(this->_data._protocolTable) = *(arts.ProtocolTableData());
      break;

    case artsC_OBJECT_TOS:
      this->_data._tosTable = new ArtsTosTableData;
      assert(this->_data._tosTable != (ArtsTosTableData *)0);
      *(this->_data._tosTable) = *(arts.TosTableData());
      break;

    case artsC_OBJECT_INTERFACE_MATRIX:
      this->_data._interfaceMatrix = new ArtsInterfaceMatrixData;
      assert(this->_data._interfaceMatrix != (ArtsInterfaceMatrixData *)0);
      *(this->_data._interfaceMatrix) = *(arts.InterfaceMatrixData());
      break;
      
    case artsC_OBJECT_NEXT_HOP:
      this->_data._nextHopTable = new ArtsNextHopTableData;
      assert(this->_data._nextHopTable != (ArtsNextHopTableData *)0);
      *(this->_data._nextHopTable) = *(arts.NextHopTableData());
      break;

    case artsC_OBJECT_BGP4:
      this->_data._bgp4RouteTable = new ArtsBgp4RouteTableData;
      assert(this->_data._bgp4RouteTable != (ArtsBgp4RouteTableData *)0);
      *(this->_data._bgp4RouteTable) = *(arts.Bgp4RouteTableData());
      break;

    case artsC_OBJECT_RTT_TIME_SERIES:
      this->_data._rttTimeSeriesTable = new ArtsRttTimeSeriesTableData;
      assert(this->_data._rttTimeSeriesTable != (ArtsRttTimeSeriesTableData *)0);
      *(this->_data._rttTimeSeriesTable) = *(arts.RttTimeSeriesTableData());
      break;
      
    default:
      break;
  }

  #ifndef NDEBUG
    ++_numObjects;
  #endif
}

//-------------------------------------------------------------------------
//                              Arts::~Arts()                              
//.........................................................................
//  destructor
//-------------------------------------------------------------------------
Arts::~Arts()
{
  #ifndef NDEBUG
    --_numObjects;
  #endif

  this->DeleteData();
  this->DeleteAttributes();
}

//----------------------------------------------------------------------------
//                      void Arts::DeleteAttributes() 
//............................................................................
//  
//----------------------------------------------------------------------------
void Arts::DeleteAttributes()
{
  if (this->_attributes.size() > 0) {
    //  delete the attributes.
    this->_attributes.erase(this->Attributes().begin(),
                            this->Attributes().end());
  }
}

//----------------------------------------------------------------------------
// ArtsAttributeVector::const_iterator Arts::FindCreationAttribute() const 
//............................................................................
//  
//----------------------------------------------------------------------------
ArtsAttributeVector::const_iterator Arts::FindCreationAttribute() const
{
  return(this->_attributes.FindCreationAttribute());
}

//----------------------------------------------------------------------------
//                   bool Arts::RemoveCreationAttribute() 
//............................................................................
//  
//----------------------------------------------------------------------------
bool Arts::RemoveCreationAttribute()
{
  return(this->_attributes.RemoveCreationAttribute());
}

//-------------------------------------------------------------------------
// ArtsAttributeVector::const_iterator Arts::FindPeriodAttribute() const
//.........................................................................
//  
//-------------------------------------------------------------------------
ArtsAttributeVector::const_iterator Arts::FindPeriodAttribute() const
{
  return(this->_attributes.FindPeriodAttribute());
}

//----------------------------------------------------------------------------
//                    bool Arts::RemovePeriodAttribute() 
//............................................................................
//  
//----------------------------------------------------------------------------
bool Arts::RemovePeriodAttribute()
{
  return(this->_attributes.RemovePeriodAttribute());
}

//-------------------------------------------------------------------------
//  ArtsAttributeVector::const_iterator Arts::FindHostAttribute() const  
//.........................................................................
//  
//-------------------------------------------------------------------------
ArtsAttributeVector::const_iterator Arts::FindHostAttribute() const
{
  return(this->_attributes.FindHostAttribute());
}

//----------------------------------------------------------------------------
//     ArtsAttributeVector::const_iterator Arts::FindHostPairAttribute() const 
//............................................................................
//  
//----------------------------------------------------------------------------
ArtsAttributeVector::const_iterator Arts::FindHostPairAttribute() const
{
  return(this->_attributes.FindHostPairAttribute());
}

//----------------------------------------------------------------------------
//                     bool Arts::RemoveHostAttribute() 
//............................................................................
//  
//----------------------------------------------------------------------------
bool Arts::RemoveHostAttribute()
{
  return(this->_attributes.RemoveHostAttribute());
}

//----------------------------------------------------------------------------
//     bool Arts::RemoveHostPairAttribute() 
//............................................................................
//  
//----------------------------------------------------------------------------
bool Arts::RemoveHostPairAttribute()
{
  return(this->_attributes.RemoveHostPairAttribute());
}

//-------------------------------------------------------------------------
// ArtsAttributeVector::const_iterator Arts::FindIfIndexAttribute() const 
//.........................................................................
//  
//-------------------------------------------------------------------------
ArtsAttributeVector::const_iterator Arts::FindIfIndexAttribute() const
{
  return(this->_attributes.FindIfIndexAttribute());
}

//----------------------------------------------------------------------------
//                   bool Arts::RemoveIfIndexAttribute() 
//............................................................................
//  
//----------------------------------------------------------------------------
bool Arts::RemoveIfIndexAttribute()
{
  return(this->_attributes.RemoveIfIndexAttribute());
}

//----------------------------------------------------------------------------
//  ArtsAttributeVector::const_iterator Arts::FindIfDescrAttribute() const 
//............................................................................
//  
//----------------------------------------------------------------------------
ArtsAttributeVector::const_iterator Arts::FindIfDescrAttribute() const
{
  return(this->_attributes.FindIfDescrAttribute());
}

//----------------------------------------------------------------------------
//                   bool Arts::RemoveIfDescrAttribute() 
//............................................................................
//  
//----------------------------------------------------------------------------
bool Arts::RemoveIfDescrAttribute()
{
  return(this->_attributes.RemoveIfDescrAttribute());
}

//----------------------------------------------------------------------------
// ArtsAttributeVector::const_iterator Arts::FindIfIpAddrAttribute() const 
//............................................................................
//  
//----------------------------------------------------------------------------
ArtsAttributeVector::const_iterator Arts::FindIfIpAddrAttribute() const
{
  return(this->_attributes.FindIfIpAddrAttribute());
}

//----------------------------------------------------------------------------
//                   bool Arts::RemoveIfIpAddrAttribute() 
//............................................................................
//  
//----------------------------------------------------------------------------
bool Arts::RemoveIfIpAddrAttribute()
{
  return(this->_attributes.RemoveIfIpAddrAttribute());
}

//------------------------------------------------------------------------
//            void Arts::AddHostAttribute(ipv4addr_t hostAddr)
//........................................................................
//
//-------------------------------------------------------------------------
void Arts::AddHostAttribute(ipv4addr_t hostAddr)
{
  this->_attributes.AddHostAttribute(hostAddr);
  this->_header.NumAttributes(this->_attributes.size());
  this->_header.AttrLength(this->_attributes.Length());
  return;
}

//----------------------------------------------------------------------------
//   void Arts::AddHostPairAttribute(ipv4addr_t host1, ipv4addr_t host2) 
//............................................................................
//  
//----------------------------------------------------------------------------
void Arts::AddHostPairAttribute(ipv4addr_t host1, ipv4addr_t host2)
{
  this->_attributes.AddHostPairAttribute(host1,host2);
  this->_header.NumAttributes(this->_attributes.size());
  this->_header.AttrLength(this->_attributes.Length());
  return;
}

//------------------------------------------------------------------------
//          void AddCreationAttribute(uint32_t creationTime)
//........................................................................
//
//------------------------------------------------------------------------
void Arts::AddCreationAttribute(uint32_t creationTime)
{
  this->_attributes.AddCreationAttribute(creationTime);
  this->_header.NumAttributes(this->_attributes.size());
  this->_header.AttrLength(this->_attributes.Length());
  return;
}

//-------------------------------------------------------------------------
//   void Arts::AddPeriodAttribute(uint32_t startTime, uint32_t endTime)
//.........................................................................
//  
//-------------------------------------------------------------------------
void Arts::AddPeriodAttribute(uint32_t startTime, uint32_t endTime)
{
  this->_attributes.AddPeriodAttribute(startTime,endTime);
  this->_header.NumAttributes(this->_attributes.size());
  this->_header.AttrLength(this->_attributes.Length());
  return;
}

//-------------------------------------------------------------------------
//             void Arts::AddIfIndexAttribute(uint16_t ifIndex)            
//.........................................................................
//  
//-------------------------------------------------------------------------
void Arts::AddIfIndexAttribute(uint16_t ifIndex)
{
  this->_attributes.AddIfIndexAttribute(ifIndex);
  this->_header.NumAttributes(this->_attributes.size());
  this->_header.AttrLength(this->_attributes.Length());
  return;
}

//----------------------------------------------------------------------------
//          void Arts::AddIfDescrAttribute(const string & ifDescr) 
//............................................................................
//  
//----------------------------------------------------------------------------
void Arts::AddIfDescrAttribute(const std::string & ifDescr)
{
  this->_attributes.AddIfDescrAttribute(ifDescr);
  this->_header.NumAttributes(this->_attributes.size());
  this->_header.AttrLength(this->_attributes.Length());
  return;
}

//----------------------------------------------------------------------------
//            void Arts::AddIfIpAddrAttribute(ipv4addr_t ipAddr) 
//............................................................................
//  
//----------------------------------------------------------------------------
void Arts::AddIfIpAddrAttribute(ipv4addr_t ipAddr)
{
  this->_attributes.AddIfIpAddrAttribute(ipAddr);
  this->_header.NumAttributes(this->_attributes.size());
  this->_header.AttrLength(this->_attributes.Length());
  return;
}

//-------------------------------------------------------------------------
//               Arts & Arts::operator = (const Arts & arts)               
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
Arts & Arts::operator = (const Arts & arts)
{
  this->DeleteData();
  
  this->_header = arts.Header();
  this->_attributes = arts.Attributes();

  switch (this->_header.Identifier()) {
    case artsC_OBJECT_IP_PATH:
      this->_data._ipPath = new ArtsIpPathData;
      assert(this->_data._ipPath != (ArtsIpPathData *)0);
      *(this->_data._ipPath) = *(arts.IpPathData());
      break;
      
    case artsC_OBJECT_AS_MATRIX:
      this->_data._asMatrix = new ArtsAsMatrixData;
      assert(this->_data._asMatrix != (ArtsAsMatrixData *)0);
      *(this->_data._asMatrix) = *(arts.AsMatrixData());
      break;

    case artsC_OBJECT_NET:
      this->_data._netMatrix = new ArtsNetMatrixData;
      assert(this->_data._netMatrix != (ArtsNetMatrixData *)0);
      *(this->_data._netMatrix) = *(arts.NetMatrixData());
      break;

    case artsC_OBJECT_PORT:
      this->_data._portTable = new ArtsPortTableData;
      assert(this->_data._portTable != (ArtsPortTableData *)0);
      *(this->_data._portTable) = *(arts.PortTableData());
      break;

    case artsC_OBJECT_SELECTED_PORT:
      this->_data._selectedPortTable = new ArtsSelectedPortTableData;
      assert(this->_data._selectedPortTable != (ArtsSelectedPortTableData *)0);
      *(this->_data._selectedPortTable) = *(arts.SelectedPortTableData());
      break;
      
    case artsC_OBJECT_PORT_MATRIX:
      this->_data._portMatrix = new ArtsPortMatrixData;
      assert(this->_data._portMatrix != (ArtsPortMatrixData *)0);
      *(this->_data._portMatrix) = *(arts.PortMatrixData());
      break;

    case artsC_OBJECT_PROTO:
      this->_data._protocolTable = new ArtsProtocolTableData;
      assert(this->_data._protocolTable != (ArtsProtocolTableData *)0);
      *(this->_data._protocolTable) = *(arts.ProtocolTableData());
      break;

    case artsC_OBJECT_TOS:
      this->_data._tosTable = new ArtsTosTableData;
      assert(this->_data._tosTable != (ArtsTosTableData *)0);
      *(this->_data._tosTable) = *(arts.TosTableData());
      break;

    case artsC_OBJECT_INTERFACE_MATRIX:
      this->_data._interfaceMatrix = new ArtsInterfaceMatrixData;
      assert(this->_data._interfaceMatrix != (ArtsInterfaceMatrixData *)0);
      *(this->_data._interfaceMatrix) = *(arts.InterfaceMatrixData());
      break;
      
    case artsC_OBJECT_NEXT_HOP:
      this->_data._nextHopTable = new ArtsNextHopTableData;
      assert(this->_data._nextHopTable != (ArtsNextHopTableData *)0);
      *(this->_data._nextHopTable) = *(arts.NextHopTableData());
      break;

    case artsC_OBJECT_BGP4:
      this->_data._bgp4RouteTable = new ArtsBgp4RouteTableData;
      assert(this->_data._bgp4RouteTable != (ArtsBgp4RouteTableData *)0);
      *(this->_data._bgp4RouteTable) = *(arts.Bgp4RouteTableData());
      break;

    case artsC_OBJECT_RTT_TIME_SERIES:
      this->_data._rttTimeSeriesTable = new ArtsRttTimeSeriesTableData;
      assert(this->_data._rttTimeSeriesTable != (ArtsRttTimeSeriesTableData *)0);
      *(this->_data._rttTimeSeriesTable) = *(arts.RttTimeSeriesTableData());
      break;
      
    default:
      break;
  }
  return(*this);
}

//-------------------------------------------------------------------------
//         std::ostream & operator << (std::ostream& os, const Arts & arts)      
//.........................................................................
//  
//-------------------------------------------------------------------------
std::ostream & operator << (std::ostream& os, const Arts & arts)
{
  os << arts.Header();

  for (int attrNum = 0; attrNum < arts.Header().NumAttributes();
       attrNum++) {
    os << arts.Attributes()[attrNum];
  }

  switch (arts.Header().Identifier()) {
    case artsC_OBJECT_IP_PATH:
      os << *(arts.IpPathData());
      break;
      
    case artsC_OBJECT_AS_MATRIX:
      os << *(arts.AsMatrixData());
      break;

    case artsC_OBJECT_NET:
      os << *(arts.NetMatrixData());
      break;

    case artsC_OBJECT_PORT:
      os << *(arts.PortTableData());
      break;

    case artsC_OBJECT_SELECTED_PORT:
      os << *(arts.SelectedPortTableData());
      break;
      
    case artsC_OBJECT_PORT_MATRIX:
      os << *(arts.PortMatrixData());
      break;
      
    case artsC_OBJECT_PROTO:
      os << *(arts.ProtocolTableData());
      break;

    case artsC_OBJECT_TOS:
      os << *(arts.TosTableData());
      break;

    case artsC_OBJECT_INTERFACE_MATRIX:
      os << *(arts.InterfaceMatrixData());
      break;

    case artsC_OBJECT_NEXT_HOP:
      os << *(arts.NextHopTableData());
      break;

    case artsC_OBJECT_BGP4:
      os << *(arts.Bgp4RouteTableData());
      break;

    case artsC_OBJECT_RTT_TIME_SERIES:
      os << *(arts.RttTimeSeriesTableData());
      break;
      
    default:
      break;
  }
  return(os);
}

//----------------------------------------------------------------------------
//            std::istream & operator >> (std::istream & is, Arts & arts) 
//............................................................................
//  
//----------------------------------------------------------------------------
std::istream & operator >> (std::istream & is, Arts & arts)
{
  arts.read(is);
  return(is);
}

//----------------------------------------------------------------------------
//                         void Arts::DeleteData() 
//............................................................................
//  
//----------------------------------------------------------------------------
void Arts::DeleteData()
{
  switch (this->_header.Identifier()) {

    case artsC_OBJECT_IP_PATH:
      if (this->_data._ipPath != (ArtsIpPathData *)0) {
        delete(this->_data._ipPath);
        this->_data._ipPath = (ArtsIpPathData *)0;
      }
      break;

    case artsC_OBJECT_AS_MATRIX:
      if (this->_data._asMatrix != (ArtsAsMatrixData *)0) {
        delete(this->_data._asMatrix);
        this->_data._asMatrix = (ArtsAsMatrixData *)0;
      }
      break;

    case artsC_OBJECT_NET:
      if (this->_data._netMatrix != (ArtsNetMatrixData *)0) {
        delete(this->_data._netMatrix);
        this->_data._netMatrix = (ArtsNetMatrixData *)0;
      }
      break;

    case artsC_OBJECT_PORT:
      if (this->_data._portTable != (ArtsPortTableData *)0) {
        delete(this->_data._portTable);
        this->_data._portTable = (ArtsPortTableData *)0;
      }
      break;

    case artsC_OBJECT_SELECTED_PORT:
      if (this->_data._selectedPortTable !=
          (ArtsSelectedPortTableData *)0) {
        delete(this->_data._selectedPortTable);
        this->_data._selectedPortTable = (ArtsSelectedPortTableData *)0;
      }
      break;
      
    case artsC_OBJECT_PORT_MATRIX:
      if (this->_data._portMatrix != (ArtsPortMatrixData *)0) {
        delete(this->_data._portMatrix);
        this->_data._portMatrix = (ArtsPortMatrixData *)0;
      }
      break;
      
    case artsC_OBJECT_PROTO:
      if (this->_data._protocolTable != (ArtsProtocolTableData *)0) {
        delete(this->_data._protocolTable);
        this->_data._protocolTable = (ArtsProtocolTableData *)0;
      }
      break;

    case artsC_OBJECT_TOS:
      if (this->_data._tosTable != (ArtsTosTableData *)0) {
        delete(this->_data._tosTable);
        this->_data._tosTable = (ArtsTosTableData *)0;
      }
      break;

    case artsC_OBJECT_INTERFACE_MATRIX:
      if (this->_data._interfaceMatrix != (ArtsInterfaceMatrixData *)0) {
        delete(this->_data._interfaceMatrix);
        this->_data._interfaceMatrix = (ArtsInterfaceMatrixData *)0;
      }
      break;
      
    case artsC_OBJECT_NEXT_HOP:
      if (this->_data._nextHopTable != (ArtsNextHopTableData *)0) {
        delete(this->_data._nextHopTable);
        this->_data._nextHopTable = (ArtsNextHopTableData *)0;
      }
      break;

    case artsC_OBJECT_BGP4:
      if (this->_data._bgp4RouteTable != (ArtsBgp4RouteTableData *)0) {
        delete(this->_data._bgp4RouteTable);
        this->_data._bgp4RouteTable = (ArtsBgp4RouteTableData *)0;
      }
      break;

    case artsC_OBJECT_RTT_TIME_SERIES:
      if (this->_data._rttTimeSeriesTable != (ArtsRttTimeSeriesTableData *)0) {
        delete(this->_data._rttTimeSeriesTable);
        this->_data._rttTimeSeriesTable = (ArtsRttTimeSeriesTableData *)0;
      }
      break;
      
    default:
      break;
  }
  this->_header.Identifier(0);
  
  return;
  
}

std::istream & Arts::readData(std::istream & is)
{
  switch (this->_header.Identifier()) {

    case artsC_OBJECT_IP_PATH:
      this->_data._ipPath = new ArtsIpPathData;
      assert(this->_data._ipPath != (ArtsIpPathData *)0);
      this->_data._ipPath->read(is, _header.Version(), _header.Flags());
      break;

    case artsC_OBJECT_AS_MATRIX:
      this->_data._asMatrix = new ArtsAsMatrixData;
      assert(this->_data._asMatrix != (ArtsAsMatrixData *)0);
      this->_data._asMatrix->read(is,this->_header.Version());
      break;

    case artsC_OBJECT_NET:
      this->_data._netMatrix = new ArtsNetMatrixData;
      assert(this->_data._netMatrix != (ArtsNetMatrixData *)0);
      this->_data._netMatrix->read(is,this->_header.Version());
      break;

    case artsC_OBJECT_PORT:
      this->_data._portTable = new ArtsPortTableData;
      assert(this->_data._portTable != (ArtsPortTableData *)0);
      this->_data._portTable->read(is,this->_header.Version());
      break;

    case artsC_OBJECT_SELECTED_PORT:
      this->_data._selectedPortTable = new ArtsSelectedPortTableData;
      assert(this->_data._selectedPortTable != (ArtsSelectedPortTableData *)0);
      this->_data._selectedPortTable->read(is,this->_header.Version());
      break;
      
    case artsC_OBJECT_PORT_MATRIX:
      this->_data._portMatrix = new ArtsPortMatrixData;
      assert(this->_data._portMatrix != (ArtsPortMatrixData *)0);
      this->_data._portMatrix->read(is,this->_header.Version());
      break;
      
    case artsC_OBJECT_PROTO:
      this->_data._protocolTable = new ArtsProtocolTableData;
      assert(this->_data._protocolTable != (ArtsProtocolTableData *)0);
      this->_data._protocolTable->read(is,this->_header.Version());
      break;

    case artsC_OBJECT_TOS:
      this->_data._tosTable = new ArtsTosTableData;
      assert(this->_data._tosTable != (ArtsTosTableData *)0);
      this->_data._tosTable->read(is,this->_header.Version());
      break;

    case artsC_OBJECT_INTERFACE_MATRIX:
      this->_data._interfaceMatrix = new ArtsInterfaceMatrixData;
      assert(this->_data._interfaceMatrix != (ArtsInterfaceMatrixData *)0);
      this->_data._interfaceMatrix->read(is,this->_header.Version());
      break;
      
    case artsC_OBJECT_NEXT_HOP:
      this->_data._nextHopTable = new ArtsNextHopTableData;
      assert(this->_data._nextHopTable != (ArtsNextHopTableData *)0);
      this->_data._nextHopTable->read(is,this->_header.Version());
      break;

    case artsC_OBJECT_BGP4:
      this->_data._bgp4RouteTable = new ArtsBgp4RouteTableData;
      assert(this->_data._bgp4RouteTable != (ArtsBgp4RouteTableData *)0);
      this->_data._bgp4RouteTable->read(is,this->_header.Version());
      break;

    case artsC_OBJECT_RTT_TIME_SERIES:
      this->_data._rttTimeSeriesTable =  new ArtsRttTimeSeriesTableData;
      assert(this->_data._rttTimeSeriesTable != (ArtsRttTimeSeriesTableData *)0);
      this->_data._rttTimeSeriesTable->read(is,this->_header.Version());
      break;
      
    default:
      fprintf(stderr,"Unknown ARTS object (id %#x) found.  Skipping data.\n",
              this->_header.Identifier());
      is.seekg(this->_header.DataLength(),std::ios::cur);
      break;
  }
  return(is);
}

//-------------------------------------------------------------------------
//                    std::istream & Arts::read(std::istream & is)                    
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
std::istream & Arts::read(std::istream & is)
{
  uint16_t       attrNum;
  ArtsAttribute  attribute;
  
  this->DeleteData();
  this->DeleteAttributes();

  if (! is)
    return(is);

  //  read the header
  this->_header.read(is);
  if (! is)
    return(is);
  
  if (this->_header.Magic() != artsC_MAGIC)
    return(is);

  //  read the attributes
  this->_attributes.read(is,this->_header.NumAttributes());
  if (! is) {
    this->DeleteAttributes();
    return(is);
  }
  
  //  read the data
  this->readData(is);
  if (! is) {
    this->DeleteData();
  }

  return(is);
}

//----------------------------------------------------------------------------
//                        int Arts::readData(int fd) 
//............................................................................
//  
//----------------------------------------------------------------------------
int Arts::readData(int fd)
{
  int  rc;
  int  bytesRead = 0;
  
  switch (this->_header.Identifier()) {
    
    case artsC_OBJECT_IP_PATH:
      this->_data._ipPath = new ArtsIpPathData;
      assert(this->_data._ipPath != (ArtsIpPathData *)0);
      rc = this->IpPathData()->read(fd, _header.Version(), _header.Flags());
      if (rc <= 0)
        return(rc);
      bytesRead += rc;
      break;

    case artsC_OBJECT_AS_MATRIX:
      this->_data._asMatrix = new ArtsAsMatrixData;
      assert(this->_data._asMatrix != (ArtsAsMatrixData *)0);
      rc = this->_data._asMatrix->read(fd,this->_header.Version());
      if (rc <= 0)
        return(rc);
      bytesRead += rc;
      break;

    case artsC_OBJECT_NET:
      this->_data._netMatrix = new ArtsNetMatrixData;
      assert(this->_data._netMatrix != (ArtsNetMatrixData *)0);
      rc = this->_data._netMatrix->read(fd,this->_header.Version());
      if (rc <= 0)
        return(rc);
      bytesRead += rc;
      break;

    case artsC_OBJECT_PORT:
      this->_data._portTable = new ArtsPortTableData;
      assert(this->_data._portTable != (ArtsPortTableData *)0);
      rc = this->_data._portTable->read(fd,this->_header.Version());
      if (rc <= 0)
        return(rc);
      bytesRead += rc;
      break;

    case artsC_OBJECT_SELECTED_PORT:
      this->_data._selectedPortTable = new ArtsSelectedPortTableData;
      assert(this->_data._selectedPortTable != (ArtsSelectedPortTableData *)0);
      this->_data._selectedPortTable->read(fd,this->_header.Version());
      if (rc <= 0)
        return(rc);
      bytesRead += rc;
      break;
      
    case artsC_OBJECT_PORT_MATRIX:
      this->_data._portMatrix = new ArtsPortMatrixData;
      assert(this->_data._portMatrix != (ArtsPortMatrixData *)0);
      rc = this->_data._portMatrix->read(fd,this->_header.Version());
      if (rc <= 0)
        return(rc);
      bytesRead += rc;
      break;

    case artsC_OBJECT_PROTO:
      this->_data._protocolTable = new ArtsProtocolTableData;
      assert(this->_data._protocolTable != (ArtsProtocolTableData *)0);
      rc = this->_data._protocolTable->read(fd,this->_header.Version());
      if (rc <= 0)
        return(rc);
      bytesRead += rc;
      break;

    case artsC_OBJECT_TOS:
      this->_data._tosTable = new ArtsTosTableData;
      assert(this->_data._tosTable != (ArtsTosTableData *)0);
      rc = this->_data._tosTable->read(fd,this->_header.Version());
      if (rc <= 0)
        return(rc);
      bytesRead += rc;
      break;

    case artsC_OBJECT_INTERFACE_MATRIX:
      this->_data._interfaceMatrix = new ArtsInterfaceMatrixData;
      assert(this->_data._interfaceMatrix != (ArtsInterfaceMatrixData *)0);
      rc = this->_data._interfaceMatrix->read(fd,this->_header.Version());
      if (rc <= 0)
        return(rc);
      bytesRead += rc;
      break;
      
    case artsC_OBJECT_NEXT_HOP:
      this->_data._nextHopTable = new ArtsNextHopTableData;
      assert(this->_data._nextHopTable != (ArtsNextHopTableData *)0);
      rc = this->_data._nextHopTable->read(fd,this->_header.Version());
      if (rc <= 0)
        return(rc);
      bytesRead += rc;
      break;

    case artsC_OBJECT_BGP4:
      this->_data._bgp4RouteTable = new ArtsBgp4RouteTableData;
      assert(this->_data._bgp4RouteTable != (ArtsBgp4RouteTableData *)0);
      rc = this->_data._bgp4RouteTable->read(fd,this->_header.Version());
      if (rc <= 0)
        return(rc);
      bytesRead += rc;
      break;

    case artsC_OBJECT_RTT_TIME_SERIES:
      this->_data._rttTimeSeriesTable = new ArtsRttTimeSeriesTableData;
      assert(this->_data._rttTimeSeriesTable !=
             (ArtsRttTimeSeriesTableData *)0);
      rc = this->_data._rttTimeSeriesTable->read(fd,this->_header.Version());
      if (rc <= 0)
        return(rc);
      bytesRead += rc;
      break;
      
    default:
      break;
  }

  return(bytesRead);
}

//-------------------------------------------------------------------------
//                       int Arts::read(int fd)                      
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
int Arts::read(int fd)
{
  ArtsAttribute   artsAttribute;
  size_t          attrNum;
  int             rc;
  int             bytesRead = 0;

  this->DeleteData();
  this->DeleteAttributes();

  //  read the header
  rc = this->_header.read(fd);
  if (rc <= 0)
    return(rc);
  bytesRead += rc;

  //  read the attributes
  rc = this->_attributes.read(fd,this->_header.NumAttributes());
  if (rc <= 0)
    return(rc);
  bytesRead += rc;

  //  read the data
  rc = this->readData(fd);
  if (rc <= 0)
    return(rc);
  bytesRead += rc;
  
  return(bytesRead);
}

//-------------------------------------------------------------------------
//                    std::ostream& Arts::write(std::ostream& os)                    
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
std::ostream& Arts::write(std::ostream& os)
{
  uint16_t   attrNum;
  
  //  Put the number of attributes and length of the attribute block
  //  in the header.  This is a sanity move in case we have broken code
  //  elsewhere.
  this->_header.NumAttributes(this->_attributes.size());
  this->_header.AttrLength(this->_attributes.Length());
  
  //  calculate the data length and put it in the header
  switch (this->_header.Identifier()) {
    case artsC_OBJECT_IP_PATH:
      this->_header.DataLength(IpPathData()->Length(_header.Version(), _header.Flags()));
      break;

    case artsC_OBJECT_AS_MATRIX:
      this->_header.DataLength(this->AsMatrixData()->Length(this->_header.Version()));
      break;
      
    case artsC_OBJECT_NET:
      this->_header.DataLength(this->NetMatrixData()->Length(this->_header.Version()));
      break;
      
    case artsC_OBJECT_PORT:
      this->_header.DataLength(this->PortTableData()->Length(this->_header.Version()));
      break;

    case artsC_OBJECT_SELECTED_PORT:
      this->_header.DataLength(this->SelectedPortTableData()->Length(this->_header.Version()));
      break;
      
    case artsC_OBJECT_PORT_MATRIX:
      this->_header.DataLength(this->PortMatrixData()->Length(this->_header.Version()));
      break;
      
    case artsC_OBJECT_PROTO:
      this->_header.DataLength(this->ProtocolTableData()->Length(this->_header.Version()));
      break;
      
    case artsC_OBJECT_TOS:
      this->_header.DataLength(this->TosTableData()->Length(this->_header.Version()));
      break;
      
    case artsC_OBJECT_INTERFACE_MATRIX:
      this->_header.DataLength(this->InterfaceMatrixData()->Length(this->_header.Version()));
      break;

    case artsC_OBJECT_NEXT_HOP:
      this->_header.DataLength(this->NextHopTableData()->Length(this->_header.Version()));
      break;

    case artsC_OBJECT_BGP4:
      this->_header.DataLength(this->Bgp4RouteTableData()->Length(this->_header.Version()));
      break;

    case artsC_OBJECT_RTT_TIME_SERIES:
      this->_header.DataLength(this->RttTimeSeriesTableData()->Length(this->_header.Version()));
      break;
      
    default:
      fprintf(stderr,
              "Unknown ARTS object (id %#x) found {%s:%d}.  Skipping data.\n",
              this->_header.Identifier(),__FILE__,__LINE__);
      break;
  }

  //  write the header
  this->_header.write(os);

  //  write the attributes
  this->_attributes.write(os);

  //  write the data
  switch (this->_header.Identifier()) {

    case artsC_OBJECT_IP_PATH:
      this->IpPathData()->write(os,this->_header.Version(), _header.Flags());
      break;

    case artsC_OBJECT_AS_MATRIX:
      this->AsMatrixData()->write(os,this->_header.Version());
      break;

    case artsC_OBJECT_NET:
      this->NetMatrixData()->write(os,this->_header.Version());
      break;

    case artsC_OBJECT_PORT:
      this->PortTableData()->write(os,this->_header.Version());
      break;

    case artsC_OBJECT_SELECTED_PORT:
      this->SelectedPortTableData()->write(os,this->_header.Version());
      break;
      
    case artsC_OBJECT_PORT_MATRIX:
      this->PortMatrixData()->write(os,this->_header.Version());
      break;

    case artsC_OBJECT_PROTO:
      this->ProtocolTableData()->write(os,this->_header.Version());
      break;
      
    case artsC_OBJECT_TOS:
      this->TosTableData()->write(os,this->_header.Version());
      break;
      
    case artsC_OBJECT_INTERFACE_MATRIX:
      this->InterfaceMatrixData()->write(os,this->_header.Version());
      break;

    case artsC_OBJECT_NEXT_HOP:
      this->NextHopTableData()->write(os,this->_header.Version());
      break;

    case artsC_OBJECT_BGP4:
      this->Bgp4RouteTableData()->write(os,this->_header.Version());
      break;

    case artsC_OBJECT_RTT_TIME_SERIES:
      this->RttTimeSeriesTableData()->write(os,this->_header.Version());
      break;
      
    default:
      fprintf(stderr,"Unknown ARTS object (id %#x) {%s:%d}\n",
              this->_header.Identifier(),__FILE__,__LINE__);
      break;
  }
  return(os);
}

//-------------------------------------------------------------------------
//                         int Arts::write(int fd)                         
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
int Arts::write(int fd)
{
  uint16_t   attrNum;
  int        rc;
  int        bytesWritten = 0;

  //  Put the number of attributes and length of the attribute block
  //  in the header.  This is a sanity move in case we have broken code
  //  elsewhere.
  this->_header.NumAttributes(this->_attributes.size());
  this->_header.AttrLength(this->_attributes.Length());
  
  //  calculate the data length and put it in the header
  switch (this->_header.Identifier()) {
    case artsC_OBJECT_IP_PATH:
      this->_header.DataLength(IpPathData()->Length(_header.Version(), _header.Flags()));
      break;

    case artsC_OBJECT_AS_MATRIX:
      this->_header.DataLength(this->AsMatrixData()->Length(this->_header.Version()));
      break;

    case artsC_OBJECT_NET:
      this->_header.DataLength(this->NetMatrixData()->Length(this->_header.Version()));
      break;

    case artsC_OBJECT_PORT:
      this->_header.DataLength(this->PortTableData()->Length(this->_header.Version()));
      break;

    case artsC_OBJECT_SELECTED_PORT:
      this->_header.DataLength(this->SelectedPortTableData()->Length(this->_header.Version()));
      break;
      
    case artsC_OBJECT_PORT_MATRIX:
      this->_header.DataLength(this->PortMatrixData()->Length(this->_header.Version()));
      break;

    case artsC_OBJECT_PROTO:
      this->_header.DataLength(this->ProtocolTableData()->Length(this->_header.Version()));
      break;
      
    case artsC_OBJECT_TOS:
      this->_header.DataLength(this->TosTableData()->Length(this->_header.Version()));
      break;
      
    case artsC_OBJECT_INTERFACE_MATRIX:
      this->_header.DataLength(this->InterfaceMatrixData()->Length(this->_header.Version()));
      break;

    case artsC_OBJECT_NEXT_HOP:
      this->_header.DataLength(this->NextHopTableData()->Length(this->_header.Version()));
      break;

    case artsC_OBJECT_BGP4:
      this->_header.DataLength(this->Bgp4RouteTableData()->Length(this->_header.Version()));
      break;

    case artsC_OBJECT_RTT_TIME_SERIES:
      this->_header.DataLength(this->RttTimeSeriesTableData()->Length(this->_header.Version()));
      break;
      
    default:
      fprintf(stderr,"Unknown ARTS object (id %#x) {%s:%d}\n",
              this->_header.Identifier(),__FILE__,__LINE__);
      break;
  }

  //  write the header
  if ((rc = this->_header.write(fd)) < 0) {
    return(-1);
  }
  bytesWritten += rc;

  //  write the attributes
  if ((rc = this->_attributes.write(fd)) < 0)
    return(-1);
  bytesWritten += rc;

  //  write the data
  switch (this->_header.Identifier()) {

    case artsC_OBJECT_IP_PATH:
      if ((rc = IpPathData()->write(fd,_header.Version(), _header.Flags())) < 0)
      {
        return(-1);
      }
      bytesWritten += rc;
      break;

    case artsC_OBJECT_AS_MATRIX:
      rc = this->AsMatrixData()->write(fd,this->_header.Version());
      if (rc < 0) {
        return(-1);
      }
      bytesWritten += rc;
      break;

    case artsC_OBJECT_NET:
      rc = this->NetMatrixData()->write(fd,this->_header.Version());
      if (rc < 0) {
        return(-1);
      }
      bytesWritten += rc;
      break;

    case artsC_OBJECT_PORT:
      rc = this->PortTableData()->write(fd,this->_header.Version());
      if (rc < 0) {
        return(-1);
      }
      bytesWritten += rc;
      break;

    case artsC_OBJECT_SELECTED_PORT:
      rc = this->SelectedPortTableData()->write(fd,this->_header.Version());
      if (rc < 0) {
        return(-1);
      }
      bytesWritten += rc;
      break;
      
    case artsC_OBJECT_PORT_MATRIX:
      rc = this->PortMatrixData()->write(fd,this->_header.Version());
      if (rc < 0) {
        return(-1);
      }
      bytesWritten += rc;
      break;

    case artsC_OBJECT_PROTO:
      rc = this->ProtocolTableData()->write(fd,this->_header.Version());
      if (rc < 0) {
        return(-1);
      }
      bytesWritten += rc;
      break;
      
    case artsC_OBJECT_TOS:
      rc = this->TosTableData()->write(fd,this->_header.Version());
      if (rc < 0) {
        return(-1);
      }
      bytesWritten += rc;
      break;
      
    case artsC_OBJECT_INTERFACE_MATRIX:
      rc = this->InterfaceMatrixData()->write(fd,this->_header.Version());
      if (rc < 0) {
        return(-1);
      }
      bytesWritten += rc;
      break;

    case artsC_OBJECT_NEXT_HOP:
      rc = this->NextHopTableData()->write(fd,this->_header.Version());
      if (rc < 0) {
        return(-1);
      }
      bytesWritten += rc;
      break;

    case artsC_OBJECT_BGP4:
      rc = this->Bgp4RouteTableData()->write(fd,this->_header.Version());
      if (rc < 0) {
        return(-1);
      }
      bytesWritten += rc;
      break;

    case artsC_OBJECT_RTT_TIME_SERIES:
      rc = this->RttTimeSeriesTableData()->write(fd,this->_header.Version());
      if (rc < 0) {
        return(-1);
      }
      bytesWritten += rc;
      break;
      
    default:
      fprintf(stderr,"Unknown ARTS object (id %#x) {%s:%d}\n",
              this->_header.Identifier(),__FILE__,__LINE__);
      break;
  }
  return(bytesWritten);
}

uint32_t Arts::_numObjects = 0;

