//===========================================================================
//  $Name: arts++-1-1-a12 $
//  $Id: ArtsAsMatrixData.cc,v 1.2 2004/04/21 23:51:31 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 "ArtsAsMatrixData.hh"
#include "ArtsPrimitive.hh"

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

//----------------------------------------------------------------------------
//                   ArtsAsMatrixData::ArtsAsMatrixData()                  
//............................................................................
//  
//----------------------------------------------------------------------------
ArtsAsMatrixData::ArtsAsMatrixData()
{
  this->_sampleInterval = 1;
  this->_count = 0;
  this->_totpkts = 0;
  this->_totbytes = 0;
  this->_orphans = 0;

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

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

//-------------------------------------------------------------------------
//   std::istream & ArtsAsMatrixData::read(std::istream& is, uint8_t version)
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
std::istream & ArtsAsMatrixData::read(std::istream& is, uint8_t version)
{
  uint32_t           entryNum;
  ArtsAsMatrixEntry  asEntry;
  
  g_ArtsLibInternal_Primitive.ReadUint16(is,this->_sampleInterval,2);
  g_ArtsLibInternal_Primitive.ReadUint32(is,this->_count,4);
  g_ArtsLibInternal_Primitive.ReadUint64(is,this->_totpkts,8);
  g_ArtsLibInternal_Primitive.ReadUint64(is,this->_totbytes,8);
  g_ArtsLibInternal_Primitive.ReadUint64(is,this->_orphans,8);
  
  this->_asEntries.reserve(this->_count);

  for (entryNum = 0; entryNum < this->_count; ++entryNum) {
    asEntry.read(is,version);
    this->_asEntries.push_back(asEntry);
  }
  return(is);
}

//-------------------------------------------------------------------------
//         int ArtsAsMatrixData::read(int fd, uint8_t version)
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
int ArtsAsMatrixData::read(int fd, uint8_t version)
{
  uint32_t           entryNum;
  ArtsAsMatrixEntry  asEntry;
  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.ReadUint32(fd,this->_count,4);
  if (rc < 4) {
    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.ReadUint64(fd,this->_orphans,8);
  if (rc < 8) {
    return(-1);
  }
  bytesRead += rc;
  
  this->_asEntries.reserve(this->_count);

  for (entryNum = 0; entryNum < this->_count; ++entryNum) {
    if ((rc = asEntry.read(fd,version)) < 0) {
      return(-1);
    }
    bytesRead += rc;
    this->_asEntries.push_back(asEntry);
  }
  return(bytesRead);
}


//-------------------------------------------------------------------------
//   std::ostream & ArtsAsMatrixData::write(std::ostream& os, uint8_t version)
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
std::ostream & ArtsAsMatrixData::write(std::ostream& os, uint8_t version)
{
  uint32_t       entryNum;

  g_ArtsLibInternal_Primitive.WriteUint16(os,this->_sampleInterval,2);
  this->_count = this->_asEntries.size();
  g_ArtsLibInternal_Primitive.WriteUint32(os,this->_count,4);
  g_ArtsLibInternal_Primitive.WriteUint64(os,this->_totpkts,8);
  g_ArtsLibInternal_Primitive.WriteUint64(os,this->_totbytes,8);
  g_ArtsLibInternal_Primitive.WriteUint64(os,this->_orphans,8);
  
  for (entryNum = 0; entryNum < this->_count; ++entryNum) {
    this->_asEntries[entryNum].write(os);
  }
  return(os);
}

//-------------------------------------------------------------------------
//         int ArtsAsMatrixData::write(int fd, uint8_t version)
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
int ArtsAsMatrixData::write(int fd, uint8_t version)
{
  uint32_t       entryNum;
  int            rc;
  int            bytesWritten = 0;

  rc = g_ArtsLibInternal_Primitive.WriteUint16(fd,this->_sampleInterval,2);
  if (rc < 2) {
    return(-1);
  }
  bytesWritten += rc;

  this->_count = this->_asEntries.size();

  rc = g_ArtsLibInternal_Primitive.WriteUint32(fd,this->_count,4);
  if (rc < 4) {
    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 = g_ArtsLibInternal_Primitive.WriteUint64(fd,this->_orphans,8);
  if (rc < 8) {
    return(-1);
    bytesWritten += rc;
  }
  
  for (entryNum = 0; entryNum < this->_count; ++entryNum) {
    if ((rc = this->_asEntries[entryNum].write(fd,version)) < 0) {
      return(-1);
    }
    bytesWritten += rc;
  }
  return(bytesWritten);
}

//-------------------------------------------------------------------------
//     uint32_t ArtsAsMatrixData::Length(uint8_t version) const
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
uint32_t ArtsAsMatrixData::Length(uint8_t version) const
{
  uint32_t  length = 0;

  length += (sizeof(this->_sampleInterval) + sizeof(this->_count) +
             sizeof(this->_totpkts) + sizeof(this->_totbytes) +
             sizeof(this->_orphans));

  std::vector<ArtsAsMatrixEntry>::const_iterator  asEntryIter;
  for (asEntryIter = this->AsEntries().begin();
       asEntryIter != this->AsEntries().end(); ++asEntryIter) {
    length += asEntryIter->Length(version);
  }
  return(length);
}

//-------------------------------------------------------------------------
//    std::ostream& operator << (std::ostream& os,                   
//                          const ArtsAsMatrixData & artsAsMatrixData)
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
std::ostream& operator << (std::ostream& os,
                      const ArtsAsMatrixData & artsAsMatrixData)
{
  using namespace std;

  os << "ASMATRIX OBJECT DATA" << endl;

  os << "\tsample_interval: " << artsAsMatrixData.SampleInterval() << endl;
  os << "\tcount: " << artsAsMatrixData.Count() << endl;
  os << "\ttotpkts: " << artsAsMatrixData.TotalPkts() << endl;
  os << "\ttotbytes: " << artsAsMatrixData.TotalBytes() << endl;
  os << "\torphans: " << artsAsMatrixData.Orphans() << endl;
  
  std::vector<ArtsAsMatrixEntry>::const_iterator  asEntryIter;

  for (asEntryIter = artsAsMatrixData.AsEntries().begin();
       asEntryIter != artsAsMatrixData.AsEntries().end(); ++asEntryIter) {
    os << (*asEntryIter);
  }
  return(os);
}

//-------------------------------------------------------------------------
//               void ArtsAsMatrixData::SortEntriesByBytes()              
//.........................................................................
//  
//-------------------------------------------------------------------------
void ArtsAsMatrixData::SortEntriesByBytes()
{
  sort(this->_asEntries.begin(),this->_asEntries.end(),
       ArtsAsMatrixEntryGreaterBytes());
  return;
}

//-------------------------------------------------------------------------
//               void ArtsAsMatrixData::SortEntriesByPkts()               
//.........................................................................
//  
//-------------------------------------------------------------------------
void ArtsAsMatrixData::SortEntriesByPkts()
{
  sort(this->_asEntries.begin(),this->_asEntries.end(),
       ArtsAsMatrixEntryGreaterPkts());
  return;
}

uint32_t  ArtsAsMatrixData::_numObjects = 0;

