//===========================================================================
//  @(#) $Name: arts++-1-1-a12 $
//  @(#) $Id: ArtsSelectedPortTableData.cc,v 1.2 2004/04/21 23:51:35 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
//===========================================================================

#include <string>
#include <algorithm>

#include "Arts.hh"
#include "ArtsPrimitive.hh"
#include "ArtsSelectedPortTableData.hh"

using namespace std;

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

//-------------------------------------------------------------------------
//        ArtsSelectedPortTableData::ArtsSelectedPortTableData()
//.........................................................................
//  
//-------------------------------------------------------------------------
ArtsSelectedPortTableData::ArtsSelectedPortTableData()
{
  this->_sampleInterval = 0;
  this->_totpkts = 0;
  this->_totbytes = 0;
  this->_length = 0;

  #ifndef NDEBUG
    ++this->_numObjects;
  #endif
}

//-------------------------------------------------------------------------
//        ArtsSelectedPortTableData::~ArtsSelectedPortTableData()
//.........................................................................
//  
//-------------------------------------------------------------------------
ArtsSelectedPortTableData::~ArtsSelectedPortTableData()
{
  #ifndef NDEBUG
    --this->_numObjects;
  #endif
}

//-------------------------------------------------------------------------
//      uint16_t ArtsSelectedPortTableData::SampleInterval() const           
//.........................................................................
//  
//-------------------------------------------------------------------------
uint16_t ArtsSelectedPortTableData::SampleInterval() const
{
  return(this->_sampleInterval);
}

//-------------------------------------------------------------------------
//   uint16_t
//   ArtsSelectedPortTableData::SampleInterval(uint16_t sampleInterval)
//.........................................................................
//  
//-------------------------------------------------------------------------
uint16_t
ArtsSelectedPortTableData::SampleInterval(uint16_t sampleInterval)
{
  this->_sampleInterval = sampleInterval;
  return(this->_sampleInterval);
}

//-------------------------------------------------------------------------
//          uint64_t ArtsSelectedPortTableData::TotalPkts() const
//.........................................................................
//  
//-------------------------------------------------------------------------
uint64_t ArtsSelectedPortTableData::TotalPkts() const
{
  return(this->_totpkts);
}

//-------------------------------------------------------------------------
//    uint64_t ArtsSelectedPortTableData::TotalPkts(uint64_t totalPkts)
//.........................................................................
//  
//-------------------------------------------------------------------------
uint64_t ArtsSelectedPortTableData::TotalPkts(uint64_t totalPkts)
{
  this->_totpkts = totalPkts;
  return(this->_totpkts);
}

//-------------------------------------------------------------------------
//          uint64_t ArtsSelectedPortTableData::TotalBytes() const
//.........................................................................
//  
//-------------------------------------------------------------------------
uint64_t ArtsSelectedPortTableData::TotalBytes() const
{
  return(this->_totbytes);
}

//-------------------------------------------------------------------------
//   uint64_t ArtsSelectedPortTableData::TotalBytes(uint64_t totalBytes)
//.........................................................................
//  
//-------------------------------------------------------------------------
uint64_t ArtsSelectedPortTableData::TotalBytes(uint64_t totalBytes)
{
  this->_totbytes = totalBytes;
  return(this->_totbytes);
}

//-------------------------------------------------------------------------
//             vector<ArtsPortTableEntry> &
//             ArtsSelectedPortTableData::PortEntries() const
//.........................................................................
//  
//-------------------------------------------------------------------------
vector<ArtsPortTableEntry> &
ArtsSelectedPortTableData::PortEntries() const
{
  return(this->_portEntries);
}

//-------------------------------------------------------------------------
//          void ArtsSelectedPortTableData::SortEntriesByBytes()              
//.........................................................................
//  
//-------------------------------------------------------------------------
void ArtsSelectedPortTableData::SortEntriesByBytes()
{
  sort(this->_portEntries.begin(),this->_portEntries.end(),
       ArtsPortEntryGreaterBytes());
  
  return;
}

//-------------------------------------------------------------------------
//          void ArtsSelectedPortTableData::SortEntriesByPkts()              
//.........................................................................
//  
//-------------------------------------------------------------------------
void ArtsSelectedPortTableData::SortEntriesByPkts()
{
  sort(this->_portEntries.begin(),this->_portEntries.end(),
       ArtsPortEntryGreaterPkts());
  
  return;
}

//-------------------------------------------------------------------------
//   uint32_t
//   ArtsSelectedPortTableData::ComputeLength(uint8_t version) const
//.........................................................................
//  
//-------------------------------------------------------------------------
uint32_t
ArtsSelectedPortTableData::ComputeLength(uint8_t version) const
{
  this->_length = 0;
  
  this->_length += sizeof(_sampleInterval);
  this->_length += sizeof(_totpkts);
  this->_length += sizeof(_totbytes);

  this->_length += this->_portChooser.Length();
  
  this->_length += sizeof(uint32_t);  // number of port entries

  vector<ArtsPortTableEntry>::const_iterator  portEntry;

  for (portEntry = this->_portEntries.begin();
       portEntry != this->_portEntries.end(); portEntry++) {
    this->_length += portEntry->Length(version);
  }
  return(this->_length);
}

//-------------------------------------------------------------------------
//     uint32_t ArtsSelectedPortTableData::Length(uint8_t version) const
//.........................................................................
//  
//-------------------------------------------------------------------------
uint32_t ArtsSelectedPortTableData::Length(uint8_t version) const
{
  this->ComputeLength(version);
  return(this->_length);
}

//-------------------------------------------------------------------------
//     istream& ArtsSelectedPortTableData::read(istream& is,
//                                              uint8_t version)
//.........................................................................
//  
//-------------------------------------------------------------------------
istream& ArtsSelectedPortTableData::read(istream& is,
                                         uint8_t version)
{
  uint32_t            numPorts;
  uint32_t            portNum;
  ArtsPortTableEntry  portEntry;
  
  g_ArtsLibInternal_Primitive.ReadUint16(is,this->_sampleInterval,2);
  g_ArtsLibInternal_Primitive.ReadUint64(is,this->_totpkts,8);
  g_ArtsLibInternal_Primitive.ReadUint64(is,this->_totbytes,8);
  this->_portChooser.read(is);
  g_ArtsLibInternal_Primitive.ReadUint32(is,numPorts,4);
  this->_portEntries.reserve(numPorts);
  for (portNum = 0; portNum < numPorts; portNum++) {
    portEntry.read(is,version);
    this->_portEntries.push_back(portEntry);
  }
  return(is);
}

//-------------------------------------------------------------------------
//         int ArtsSelectedPortTableData::read(int fd, uint8_t version)
//.........................................................................
//  
//-------------------------------------------------------------------------
int ArtsSelectedPortTableData::read(int fd, uint8_t version)
{
  uint32_t            numPorts;
  uint32_t            portNum;
  ArtsPortTableEntry  portEntry;
  int                 rc;
  int                 bytesRead = 0;

  rc = g_ArtsLibInternal_Primitive.ReadUint16(fd,this->_sampleInterval,2);
  if (rc < 2)
    return(-1);
  bytesRead += rc;
  rc = g_ArtsLibInternal_Primitive.ReadUint64(fd,this->_totpkts,8);
  if (rc < 8)
    return(-1);
  bytesRead += rc;
  rc = g_ArtsLibInternal_Primitive.ReadUint64(fd,this->_totbytes,8);
  if (rc < 8)
    return(-1);
  bytesRead += rc;
  rc = this->_portChooser.read(fd);
  if (rc < 0)
    return(-1);
  bytesRead += rc;
  
  rc = g_ArtsLibInternal_Primitive.ReadUint32(fd,numPorts,4);
  if (rc < 4)
    return(-1);
  bytesRead += rc;
  for (portNum = 0; portNum < numPorts; portNum++) {
    rc = portEntry.read(fd,version);
    if (rc < 0)
      return(rc);
    bytesRead += rc;
    this->_portEntries.push_back(portEntry);
  }

  return(bytesRead);
}

//-------------------------------------------------------------------------
//      ostream& ArtsSelectedPortTableData::write(ostream& os,
//                                        uint8_t version) const
//.........................................................................
//  
//-------------------------------------------------------------------------
ostream& ArtsSelectedPortTableData::write(ostream& os,
                                  uint8_t version) const
{
  uint32_t                                    numPorts;
  vector<ArtsPortTableEntry>::const_iterator  portEntry;
  
  g_ArtsLibInternal_Primitive.WriteUint16(os,this->_sampleInterval,2);
  g_ArtsLibInternal_Primitive.WriteUint64(os,this->_totpkts,8);
  g_ArtsLibInternal_Primitive.WriteUint64(os,this->_totbytes,8);
  this->_portChooser.write(os);
  numPorts = this->_portEntries.size();
  g_ArtsLibInternal_Primitive.WriteUint32(os,numPorts,4);

  for (portEntry = this->_portEntries.begin();
       portEntry != this->_portEntries.end(); portEntry++) {
    portEntry->write(os,version);
  }

  return(os);
}

//-------------------------------------------------------------------------
//     int ArtsSelectedPortTableData::write(int fd, uint8_t version) const
//.........................................................................
//  
//-------------------------------------------------------------------------
int ArtsSelectedPortTableData::write(int fd, uint8_t version) const
{
  uint32_t      numPorts;
  int           rc;
  int           bytesWritten = 0;
  
  rc = g_ArtsLibInternal_Primitive.WriteUint16(fd,this->_sampleInterval,2);
  if (rc < 2)
    return(-1);
  bytesWritten += rc;
  
  rc = g_ArtsLibInternal_Primitive.WriteUint64(fd,this->_totpkts,8);
  if (rc < 8)
    return(-1);
  bytesWritten += rc;

  rc = g_ArtsLibInternal_Primitive.WriteUint64(fd,this->_totbytes,8);
  if (rc < 8)
    return(-1);
  bytesWritten += rc;

  rc = this->_portChooser.write(fd);
  if (rc < 0)
    return(-1);
  bytesWritten += rc;
  
  numPorts = this->_portEntries.size();
  g_ArtsLibInternal_Primitive.WriteUint32(fd,numPorts,4);
  if (rc < 4)
    return(-1);
  bytesWritten += rc;

  vector<ArtsPortTableEntry>::const_iterator  portEntry;
  
  for (portEntry = this->_portEntries.begin();
       portEntry != this->_portEntries.end(); portEntry++) {
    rc = portEntry->write(fd,version);
    if (rc < 0)
      return(rc);
    bytesWritten += rc;
  }

  return(bytesWritten);
}

//-------------------------------------------------------------------------
// ArtsSelectedPortTableData &                           
// ArtsSelectedPortTableData::operator = (const ArtsSelectedPortTableData & artsSelectedPortTableData) 
//.........................................................................
//  
//-------------------------------------------------------------------------
ArtsSelectedPortTableData &
ArtsSelectedPortTableData::operator = (const ArtsSelectedPortTableData & artsSelectedPortTableData)
{
  this->_sampleInterval = artsSelectedPortTableData.SampleInterval();
  this->_totpkts = artsSelectedPortTableData.TotalPkts();
  this->_totbytes = artsSelectedPortTableData.TotalBytes();
  this->_portEntries = artsSelectedPortTableData.PortEntries();
  this->_length = artsSelectedPortTableData.Length();
  this->_portChooser = artsSelectedPortTableData.PortChooser();
  
  return(*this);
}

//-------------------------------------------------------------------------
//   ostream & operator << (ostream& os,                   
//           const ArtsSelectedPortTableData & artsSelectedPortTableData) 
//.........................................................................
//  
//-------------------------------------------------------------------------
ostream& operator << (ostream& os,
             const ArtsSelectedPortTableData & artsSelectedPortTableData)
{
  os << "SELECTED PORT OBJECT DATA" << endl;
  os << artsSelectedPortTableData.PortChooser();

  os << "    PORT TRAFFIC DATA" << endl;
  os << "\tsample_interval: " << artsSelectedPortTableData.SampleInterval()
     << endl;
  os << "\tcount: " << artsSelectedPortTableData.PortEntries().size() << endl;
  os << "\ttotpkts: " << artsSelectedPortTableData.TotalPkts() << endl;
  os << "\ttotbytes: " << artsSelectedPortTableData.TotalBytes() << endl;
  
  vector<ArtsPortTableEntry>::const_iterator  portEntry;
  for (portEntry = artsSelectedPortTableData.PortEntries().begin();
       portEntry != artsSelectedPortTableData.PortEntries().end();
       portEntry++) {
    os << *portEntry;
  }
  return(os);
}

uint32_t ArtsSelectedPortTableData::_numObjects = 0;
