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

using namespace std;

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

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

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

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

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

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

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

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

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

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

//-------------------------------------------------------------------------
//            vector<ArtsNextHopTableEntry> &
//            ArtsNextHopTableData::NextHopEntries() const
//.........................................................................
//  
//-------------------------------------------------------------------------
vector<ArtsNextHopTableEntry> &
ArtsNextHopTableData::NextHopEntries() const
{
  return(this->_NextHopEntries);
}

//-------------------------------------------------------------------------
//             void ArtsNextHopTableData::SortEntriesByBytes()            
//.........................................................................
//  
//-------------------------------------------------------------------------
void ArtsNextHopTableData::SortEntriesByBytes()
{
  sort(this->_NextHopEntries.begin(),this->_NextHopEntries.end(),
       ArtsNextHopEntryGreaterBytes());
  return;
}

//-------------------------------------------------------------------------
//             void ArtsNextHopTableData::SortEntriesByPkts()            
//.........................................................................
//  
//-------------------------------------------------------------------------
void ArtsNextHopTableData::SortEntriesByPkts()
{
  sort(this->_NextHopEntries.begin(),this->_NextHopEntries.end(),
       ArtsNextHopEntryGreaterPkts());
  return;
}

//-------------------------------------------------------------------------
// uint32_t ArtsNextHopTableData::ComputeLength(uint8_t version) const
//.........................................................................
//  
//-------------------------------------------------------------------------
uint32_t ArtsNextHopTableData::ComputeLength(uint8_t version) const
{
  this->_length = 0;
  
  this->_length += sizeof(_sampleInterval);
  this->_length += sizeof(_totpkts);
  this->_length += sizeof(_totbytes);
  this->_length += sizeof(uint32_t);  // number of NextHop entries

  vector<ArtsNextHopTableEntry>::const_iterator  NextHopEntry;

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

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

//-------------------------------------------------------------------------
// istream& ArtsNextHopTableData::read(istream& is, uint8_t version)
//.........................................................................
//  
//-------------------------------------------------------------------------
istream& ArtsNextHopTableData::read(istream& is, uint8_t version)
{
  uint32_t            numNextHops;
  uint32_t            NextHopNum;
  ArtsNextHopTableEntry  NextHopEntry;
  
  g_ArtsLibInternal_Primitive.ReadUint16(is,this->_sampleInterval,2);
  g_ArtsLibInternal_Primitive.ReadUint64(is,this->_totpkts,8);
  g_ArtsLibInternal_Primitive.ReadUint64(is,this->_totbytes,8);
  g_ArtsLibInternal_Primitive.ReadUint32(is,numNextHops,4);
  this->_NextHopEntries.reserve(numNextHops);
  for (NextHopNum = 0; NextHopNum < numNextHops; NextHopNum++) {
    NextHopEntry.read(is,version);
    this->_NextHopEntries.push_back(NextHopEntry);
  }
  return(is);
}

//-------------------------------------------------------------------------
//      int ArtsNextHopTableData::read(int fd, uint8_t version)
//.........................................................................
//  
//-------------------------------------------------------------------------
int ArtsNextHopTableData::read(int fd, uint8_t version)
{
  uint32_t            numNextHops;
  uint32_t            NextHopNum;
  ArtsNextHopTableEntry  NextHopEntry;
  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 = g_ArtsLibInternal_Primitive.ReadUint32(fd,numNextHops,4);
  if (rc < 4)
    return(-1);
  bytesRead += rc;
  for (NextHopNum = 0; NextHopNum < numNextHops; NextHopNum++) {
    rc = NextHopEntry.read(fd,version);
    if (rc < 0)
      return(rc);
    bytesRead += rc;
    this->_NextHopEntries.push_back(NextHopEntry);
  }

  return(bytesRead);
}

//-------------------------------------------------------------------------
//    ostream& ArtsNextHopTableData::write(ostream& os,
//                                          uint8_t version) const
//.........................................................................
//  
//-------------------------------------------------------------------------
ostream& ArtsNextHopTableData::write(ostream& os,
                                      uint8_t version) const
{
  uint32_t            numNextHops;
  
  g_ArtsLibInternal_Primitive.WriteUint16(os,this->_sampleInterval,2);
  g_ArtsLibInternal_Primitive.WriteUint64(os,this->_totpkts,8);
  g_ArtsLibInternal_Primitive.WriteUint64(os,this->_totbytes,8);
  numNextHops = this->_NextHopEntries.size();
  g_ArtsLibInternal_Primitive.WriteUint32(os,numNextHops,4);

  vector<ArtsNextHopTableEntry>::const_iterator  NextHopEntry;
  
  for (NextHopEntry = this->_NextHopEntries.begin();
       NextHopEntry != this->_NextHopEntries.end(); NextHopEntry++) {
    NextHopEntry->write(os,version);
  }

  return(os);
}

//-------------------------------------------------------------------------
//  int ArtsNextHopTableData::write(int fd, uint8_t version) const
//.........................................................................
//  
//-------------------------------------------------------------------------
int ArtsNextHopTableData::write(int fd, uint8_t version) const
{
  uint32_t      numNextHops;
  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;

  numNextHops = this->_NextHopEntries.size();
  g_ArtsLibInternal_Primitive.WriteUint32(fd,numNextHops,4);
  if (rc < 4)
    return(-1);
  bytesWritten += rc;

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

  return(bytesWritten);
}

//-------------------------------------------------------------------------
//  ArtsNextHopTableData &                           
//  operator = (const ArtsNextHopTableData & artsNextHopTableData) 
//.........................................................................
//  
//-------------------------------------------------------------------------
ArtsNextHopTableData &
ArtsNextHopTableData::operator = (const ArtsNextHopTableData & artsNextHopTableData)
{
  this->_sampleInterval = artsNextHopTableData.SampleInterval();
  this->_totpkts = artsNextHopTableData.TotalPkts();
  this->_totbytes = artsNextHopTableData.TotalBytes();
  this->_NextHopEntries = artsNextHopTableData.NextHopEntries();
  this->_length = artsNextHopTableData.Length();
  return(*this);
}

//-------------------------------------------------------------------------
//    ostream &
//    operator << (ostream& os,                   
//                 const ArtsNextHopTableData & artsNextHopTableData) 
//.........................................................................
//  
//-------------------------------------------------------------------------
ostream & operator << (ostream& os,
                       const ArtsNextHopTableData & artsNextHopTableData)
{
  os << "NEXTHOP OBJECT DATA" << endl;
  os << "\tsample_interval: " << artsNextHopTableData.SampleInterval()
     << endl;
  os << "\tcount: " << artsNextHopTableData.NextHopEntries().size() << endl;
  os << "\ttotpkts: " << artsNextHopTableData.TotalPkts() << endl;
  os << "\ttotbytes: " << artsNextHopTableData.TotalBytes() << endl;

  vector<ArtsNextHopTableEntry>::const_iterator  NextHopEntry;

  for (NextHopEntry = artsNextHopTableData.NextHopEntries().begin();
       NextHopEntry != artsNextHopTableData.NextHopEntries().end();
       NextHopEntry++) {
    os << *NextHopEntry;
  }
  
  return(os);
}

uint32_t ArtsNextHopTableData::_numObjects = 0;
