//===========================================================================
//  $Name: arts++-1-1-a12 $
//  $Id: ArtsBgp4AsPathAttribute.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 "ArtsPrimitive.hh"
#include "ArtsBgp4AsPathAttribute.hh"

using namespace std;

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

//----------------------------------------------------------------------------
//            ArtsBgp4AsPathAttribute::ArtsBgp4AsPathAttribute()           
//............................................................................
//  
//----------------------------------------------------------------------------
ArtsBgp4AsPathAttribute::ArtsBgp4AsPathAttribute()
{
  #ifndef NDEBUG
    ++_numObjects;
  #endif
}

//----------------------------------------------------------------------------
//           ArtsBgp4AsPathAttribute::~ArtsBgp4AsPathAttribute()           
//............................................................................
//  
//----------------------------------------------------------------------------
ArtsBgp4AsPathAttribute::~ArtsBgp4AsPathAttribute()
{
  #ifndef NDEBUG
    --_numObjects;
  #endif
}

//-------------------------------------------------------------------------
//          uint8_t ArtsBgp4AsPathAttribute::NumSegments() const
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
uint8_t ArtsBgp4AsPathAttribute::NumSegments() const
{
  return(this->_segments.size());
}

//-------------------------------------------------------------------------
//             vector<ArtsBgp4AsPathSegment> &
//             ArtsBgp4AsPathAttribute::Segments() const
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
vector<ArtsBgp4AsPathSegment> & ArtsBgp4AsPathAttribute::Segments() const
{
  return(this->_segments);
}

//-------------------------------------------------------------------------
//  ArtsBgp4AsPathAttribute &                        
//  ArtsBgp4AsPathAttribute::operator = (const ArtsBgp4AsPathAttribute &
//                                       asPath) 
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
ArtsBgp4AsPathAttribute &
ArtsBgp4AsPathAttribute::operator = (const ArtsBgp4AsPathAttribute & asPath)
{
  if (this->_segments.size() > 0)
    this->_segments.erase(this->_segments.begin(),this->_segments.end());
  if (asPath.Segments().size() > 0) {
    this->_segments.reserve(asPath.Segments().size());
    this->_segments = asPath.Segments();
  }
  
  return(*this);
}

//----------------------------------------------------------------------------
// istream & ArtsBgp4AsPathAttribute::read(istream & is, uint8_t version) 
//............................................................................
//  
//----------------------------------------------------------------------------
istream & ArtsBgp4AsPathAttribute::read(istream & is, uint8_t version)
{
  ArtsBgp4AsPathSegment  asPathSegment;
  uint8_t                numSegments;

  if (this->_segments.size() > 0)
    this->_segments.erase(this->_segments.begin(),this->_segments.end());
  
  is.read((char*)&numSegments,sizeof(numSegments));
  if (numSegments > 0) {
    this->_segments.reserve(numSegments);
    for (uint8_t segmentNum = 0; segmentNum < numSegments; segmentNum++) {
      asPathSegment.read(is,version);
      this->_segments.push_back(asPathSegment);
      asPathSegment.AS().erase(asPathSegment.AS().begin(),
                               asPathSegment.AS().end());
    }
  }
  
  return(is);
}

//----------------------------------------------------------------------------
//      int ArtsBgp4AsPathAttribute::read(int fd, uint8_t version)     
//............................................................................
//  
//----------------------------------------------------------------------------
int ArtsBgp4AsPathAttribute::read(int fd, uint8_t version)
{
  int                    rc;
  int                    bytesRead = 0;
  uint8_t                numSegments;
  ArtsBgp4AsPathSegment  asPathSegment;
  
  rc = g_ArtsLibInternal_Primitive.FdRead(fd,&numSegments,sizeof(numSegments));
  if (rc < sizeof(numSegments))
    return(-1);
  bytesRead += rc;
  this->_segments.reserve(numSegments);
  for (uint8_t segmentNum = 0; segmentNum < numSegments; segmentNum++) {
    rc = asPathSegment.read(fd,version);
    if (rc < 0)
      return(-1);
    bytesRead += rc;
    this->_segments.push_back(asPathSegment);
    asPathSegment.AS().erase(asPathSegment.AS().begin(),
                             asPathSegment.AS().end());
  }
  return(bytesRead);
}

//----------------------------------------------------------------------------
//    ostream & ArtsBgp4AsPathAttribute::write(ostream & os,
//                                             uint8_t version) const 
//............................................................................
//  
//----------------------------------------------------------------------------
ostream & ArtsBgp4AsPathAttribute::write(ostream & os,
                                         uint8_t version) const
{
  uint8_t                numSegments = this->_segments.size();
  os.write((char*)&numSegments,sizeof(numSegments));
  for (uint8_t segmentNum = 0; segmentNum < numSegments; segmentNum++) {
    this->_segments[segmentNum].write(os,version);
  }
  return(os);
}

//----------------------------------------------------------------------------
//  int ArtsBgp4AsPathAttribute::write(int fd, uint8_t version) const  
//............................................................................
//  
//----------------------------------------------------------------------------
int ArtsBgp4AsPathAttribute::write(int fd, uint8_t version) const
{
  int        rc;
  int        bytesWritten = 0;
  uint8_t    numSegments = this->_segments.size();

  rc = g_ArtsLibInternal_Primitive.FdWrite(fd,&numSegments,
                                           sizeof(numSegments));
  if (rc < sizeof(numSegments))
    return(-1);
  bytesWritten += rc;
  for (uint8_t segmentNum = 0; segmentNum < numSegments; segmentNum++) {
    rc = this->_segments[segmentNum].write(fd,version);
    if (rc < 0)
      return(-1);
    bytesWritten += rc;
  }
  return(bytesWritten);
}

//----------------------------------------------------------------------------
//                  void ArtsBgp4AsPathAttribute::Unique()                 
//............................................................................
//  
//----------------------------------------------------------------------------
void ArtsBgp4AsPathAttribute::Unique()
{
  vector<ArtsBgp4AsPathSegment>::iterator   segIter;
  for (segIter = this->_segments.begin(); segIter != this->_segments.end();
       segIter++) {
    if ((*segIter).Type() == ArtsBgp4AsPathSegment::k_segmentTypeSequence) {
      (*segIter).Unique();
    }
  }
  return;
}

//----------------------------------------------------------------------------
//   uint32_t ArtsBgp4AsPathAttribute::Length(uint8_t version) const   
//............................................................................
//  
//----------------------------------------------------------------------------
uint32_t ArtsBgp4AsPathAttribute::Length(uint8_t version) const
{
  uint32_t  length = sizeof(uint8_t);

  vector<ArtsBgp4AsPathSegment>::iterator  segIter;
  for (segIter = this->_segments.begin(); segIter != this->_segments.end();
       segIter++) {
    length += segIter->Length();
  }
  return(length);
}

//----------------------------------------------------------------------------
//      ostream &                                
//      operator << (ostream & os,               
//                   const ArtsBgp4AsPathAttribute & bgp4AsPathAttribute) 
//............................................................................
//  
//----------------------------------------------------------------------------
ostream &
operator << (ostream & os,
             const ArtsBgp4AsPathAttribute & bgp4AsPathAttribute)
{
  vector<ArtsBgp4AsPathSegment>::iterator  segIter;
  if (bgp4AsPathAttribute.Segments().size() > 0) {
    for (segIter = bgp4AsPathAttribute.Segments().begin();
         segIter != bgp4AsPathAttribute.Segments().end();
         segIter++) {
      os << (*segIter) << " ";
    }
  }
  
  return(os);
}


uint32_t ArtsBgp4AsPathAttribute::_numObjects = 0;
