//===========================================================================
// @(#) $Name: arts++-1-1-a12 $
// @(#) $Id: ArtsPrimitive.cc,v 1.2 2004/04/21 23:51:34 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 <sys/types.h>
#include <unistd.h>
#include <netinet/in.h>
#include <rpc/rpc.h>
#include <rpc/xdr.h>
#include <assert.h>
#include "aclocal.h"
}

//---------------------------------------------------------------------------
//  The xdr_destroy() macro in <rpc/xdr.h> on FreeBSD 2.2.x systems (and
//  possibly others) is broken... it passes the XDR pointer to the
//  x_destroy() function but the x_destroy() function prototype
//  doesn't have any arguments.  C++ compilers (and rigorous C compilers)
//  don't like this, so we'll rewrite the macro to match the x_destroy()
//  prototype if XDR_DESTROY_MACRO_DONT_PASS_POINTER is defined.
//---------------------------------------------------------------------------
#ifdef XDR_DESTROY_MACRO_DONT_PASS_POINTER
  #undef xdr_destroy(xdrs)
  #define xdr_destroy(xdrs)                     \
    if ((xdrs)->x_ops->x_destroy)               \
      (*(xdrs)->x_ops->x_destroy)()
#endif

#include <string>

#include "ArtsPrimitive.hh"

using namespace std;

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

//-------------------------------------------------------------------------
// int ArtsPrimitive::FdWrite(int fd, const char *ptr, int numBytes) const
//.........................................................................
//  
//-------------------------------------------------------------------------
int ArtsPrimitive::FdWrite(int fd, const void *ptr, int numBytes) const
{
  int    nleft, nwritten;
  char  *myptr;

  #ifdef ARTS_DEBUG_DO_ASSERTIONS
    assert(fd >= 0);
    assert(ptr != (void *)0);
    assert(numBytes > 0);
  #endif

  myptr = (char *)ptr;
  
  nleft = numBytes;

  while (nleft > 0) {
    nwritten = ::write(fd,myptr,nleft);
    if (nwritten <= 0)
      return(nwritten);
    nleft -= nwritten;
    myptr += nwritten;
  }
  return(numBytes - nleft);
}

//----------------------------------------------------------------------------
//     int ArtsPrimitive::FdRead(int fd, void *ptr, int numBytes) const 
//............................................................................
//  
//----------------------------------------------------------------------------
int ArtsPrimitive::FdRead(int fd, void *ptr, int numBytes) const
{
  int   nleft, nread;
  char *myptr;
    
  #ifdef ARTS_DEBUG_DO_ASSERTIONS
    assert(fd >= 0);
    assert(ptr != (void *)0);
    assert(numBytes > 0);
  #endif

  myptr = (char *)ptr;
    
  nleft = numBytes;
  
  while (nleft > 0) {
    nread = ::read(fd,myptr,nleft);
    if (nread < 0){
      return(nread);
    }
    else {
      if (nread == 0) {
        break;
      }
    }
    nleft -= nread;
    myptr += nread;
  }
  return(numBytes - nleft);
}

//------------------------------------------------------------------------
//   ArtsPrimitive::WriteUint16(ostream & os, const uint16_t & value,
//                              uint8_t len) const
//------------------------------------------------------------------------
ostream & ArtsPrimitive::WriteUint16(ostream & os, const uint16_t & value,
                                     uint8_t len) const
{
  uint16_t  val16;
  uint8_t   val8;

  switch (len) {
    case 1:
      val8 = value;
      os.write((char*)&val8,sizeof(val8));
      break;
    case 2:
      val16 = htons(value);
      os.write((char*)&val16,sizeof(val16));
      break;
    default:
      #ifdef ARTS_DEBUG_DO_ASSERTIONS
        assert((len == 1) || (len == 2));
      #endif
      break;
  }

  return(os);
}

//-------------------------------------------------------------------------
//      int ArtsPrimitive::WriteUint16(int fd, const uint16_t & value,     
//                                     uint8_t len) const
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
int ArtsPrimitive::WriteUint16(int fd, const uint16_t & value,
                               uint8_t len) const
{
  uint16_t  val16;
  uint8_t   val8;
  int       rc = -1;

  #ifdef ARTS_DEBUG_DO_ASSERTIONS
    assert(fd >= 0);
  #endif

  switch (len) {
    case 1:
      val8 = value;
      rc = this->FdWrite(fd,&val8,sizeof(val8));
      break;
    case 2:
      val16 = htons(value);
      rc = this->FdWrite(fd,&val16,sizeof(val16));
      break;
    default:
      #ifdef ARTS_DEBUG_DO_ASSERTIONS
        assert((len == 1) || (len == 2));
      #endif
      break;
  }
  if (rc != len)
    return(-1);
  
  return(rc);
}

//-------------------------------------------------------------------------
//   istream & ArtsPrimitive::ReadUint16(istream & is, uint16_t & value,   
//                                       uint8_t len) const
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
istream & ArtsPrimitive::ReadUint16(istream & is, uint16_t & value,
                                    uint8_t len) const
{
  uint16_t  val16;
  uint8_t   val8;

  switch (len) {
    case 1:
      is.read((char*)&val8,sizeof(val8));
      value = val8;
      break;
    case 2:
      is.read((char*)&val16,sizeof(val16));
      value = ntohs(val16);
      break;
    default:
      #ifdef ARTS_DEBUG_DO_ASSERTIONS
        assert((len == 1) || (len == 2));
      #endif
      break;
  }

  return(is);
}

//-------------------------------------------------------------------------
//         int ArtsPrimitive::ReadUint16(int fd, uint16_t & value,         
//                                       uint8_t len) const
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
int ArtsPrimitive::ReadUint16(int fd, uint16_t & value,
                              uint8_t len) const
{
  uint16_t  val16;
  uint8_t   val8;
  int       rc = -1;

  #ifdef ARTS_DEBUG_DO_ASSERTIONS
    assert(fd >= 0);
  #endif
        
  switch (len) {
    case 1:
      rc = this->FdRead(fd,&val8,sizeof(val8));
      value = val8;
      break;
    case 2:
      rc = this->FdRead(fd,&val16,sizeof(val16));
      value = ntohs(val16);
      break;
    default:
      #ifdef ARTS_DEBUG_DO_ASSERTIONS
        assert((len == 1) || (len == 2));
      #endif
      break;
  }
  if (rc != len)
    return(-1);
  
  return(rc);
}

//-------------------------------------------------------------------------
// ostream & ArtsPrimitive::WriteUint32(ostream & os, const uint32_t & value, 
//                                      uint8_t len) const
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
ostream & ArtsPrimitive::WriteUint32(ostream & os, const uint32_t & value,
                                     uint8_t len) const
{
  uint32_t  val32;
  uint16_t  val16;
  uint8_t   val8;

  switch (len) {
    case 1:
      val8 = value;
      os.write((char*)&val8,sizeof(val8));
      break;
    case 2:
      val16 = value;
      val16 = htons(val16);
      os.write((char*)&val16,sizeof(val16));
      break;
    case 3:
      val8 = (value >> 16);
      os.write((char*)&val8,sizeof(val8));
      val16 = htons((value & 0x0000ffff));
      os.write((char*)&val16,sizeof(val16));
      break;
    case 4:
      val32 = value;
      val32 = htonl(value);
      os.write((char*)&val32,sizeof(val32));
      break;
    default:
      #ifdef ARTS_DEBUG_DO_ASSERTIONS
        assert((len == 1) || (len == 2) || (len == 3) || (len == 4));
      #endif
      break;
  }

  return(os);
}

//-------------------------------------------------------------------------
//      int ArtsPrimitive::WriteUint32(int fd, const uint32_t & value,     
//                                     uint8_t len) const
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
int ArtsPrimitive::WriteUint32(int fd, const uint32_t & value,
                               uint8_t len) const
{
  uint32_t  val32;
  uint16_t  val16;
  uint8_t   val8;
  int       rc = -1;
  
  #ifdef ARTS_DEBUG_DO_ASSERTIONS
    assert(fd >= 0);
  #endif

  switch (len) {
    case 1:
      val8 = value;
      rc = this->FdWrite(fd,&val8,sizeof(val8));
      return(rc);
      break;
    case 2:
      val16 = value;
      val16 = htons(val16);
      rc = this->FdWrite(fd,&val16,sizeof(val16));
      break;
    case 3:
      val8 = (value >> 16);
      rc = this->FdWrite(fd,&val8,sizeof(val8));
      val16 = htons((value & 0x0000ffff));
      rc += this->FdWrite(fd,&val16,sizeof(val16));
      break;
    case 4:
      val32 = value;
      val32 = htonl(value);
      rc = this->FdWrite(fd,&val32,sizeof(val32));
      break;
    default:
      #ifdef ARTS_DEBUG_DO_ASSERTIONS
        assert((len == 1) || (len == 2) || (len == 3) || (len == 4));
      #endif
      break;
  }
  if (rc != len)
    return(-1);
  
  return(rc);
}

//-------------------------------------------------------------------------
//   istream & ArtsPrimitive::ReadUint32(istream & is, uint32_t & value,   
//                                       uint8_t len) const
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
istream & ArtsPrimitive::ReadUint32(istream & is, uint32_t & value,
                                    uint8_t len) const
{
  uint32_t  val32;
  uint16_t  val16;
  uint8_t   val8;

  switch (len) {
    case 1:
      is.read((char*)&val8,sizeof(val8));
      value = val8;
      break;
    case 2:
      is.read((char*)&val16,sizeof(val16));
      value = ntohs(val16);
      break;
    case 3:
      is.read((char*)&val8,sizeof(val8));
      value = ((uint32_t)val8) << 16;
      is.read((char*)&val16,sizeof(val16));
      value |= ntohs(val16);
      break;
    case 4:
      is.read((char*)&val32,sizeof(val32));
      value = ntohl(val32);
      break;
    default:
      #ifdef ARTS_DEBUG_DO_ASSERTIONS
        assert((len == 1) || (len == 2) || (len == 3) || (len == 4));
      #endif
      break;
  }

  return(is);
}

//-------------------------------------------------------------------------
//         int ArtsPrimitive::ReadUint32(int fd, uint32_t & value,         
//                                       uint8_t len) const
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
int ArtsPrimitive::ReadUint32(int fd, uint32_t & value,
                              uint8_t len) const
{
  uint32_t  val32;
  uint16_t  val16;
  uint8_t   val8;
  int       rc;
  int       bytesRead = 0;
  
  #ifdef ARTS_DEBUG_DO_ASSERTIONS
    assert(fd >= 0);
  #endif

  switch (len) {
    case 1:
      bytesRead = this->FdRead(fd,&val8,sizeof(val8));
      value = val8;
      break;
    case 2:
      bytesRead = this->FdRead(fd,&val16,sizeof(val16));
      value = ntohs(val16);
      break;
    case 3:
      rc = this->FdRead(fd,&val8,sizeof(val8));
      if (rc < sizeof(val8))
        break;
      bytesRead += rc;
      value = ((uint32_t)val8) << 16;
      rc = this->FdRead(fd,&val16,sizeof(val16));
      if (rc < sizeof(val16))
        break;
      bytesRead += rc;
      value |= ntohs(val16);
      break;
    case 4:
      bytesRead = this->FdRead(fd,&val32,sizeof(val32));
      value = ntohl(val32);
      break;
    default:
      #ifdef ARTS_DEBUG_DO_ASSERTIONS
        assert((len == 1) || (len == 2) || (len == 3) || (len == 4));
      #endif
      break;
  }
  if (bytesRead != len)
    return(-1);
  
  return(bytesRead);
}

//-------------------------------------------------------------------------
// ostream & ArtsPrimitive::WriteUint64(ostream & os, const uint64_t & value, 
//                                      uint8_t len) const
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
ostream & ArtsPrimitive::WriteUint64(ostream & os, const uint64_t & value,
                                     uint8_t len) const
{
  uint32_t  valuePart[2];
  uint16_t  val16;
  uint8_t   val8;

  switch (len) {
    case 1:
      val8 = value;
      os.write((char*)&val8,sizeof(val8));
      break;
    case 2:
      val16 = value;
      val16 = htons(val16);
      os.write((char*)&val16,sizeof(val16));
      break;
    case 4:
      valuePart[0] = value;
      valuePart[0] = htonl(value);
      os.write((char*)&valuePart[0],sizeof(uint32_t));
      break;
    case 8:
      valuePart[0] = htonl(value >> 32);
      valuePart[1] = htonl(value & 0xffffffff);
      os.write((char*)valuePart,sizeof(valuePart));
      break;
    default:
      #ifdef ARTS_DEBUG_DO_ASSERTIONS
        assert((len == 1) || (len == 2) || (len == 4) || (len == 8));
      #endif
      break;
  }

  return(os);
}

//-------------------------------------------------------------------------
//      int ArtsPrimitive::WriteUint64(int fd, const uint64_t & value,     
//                                     uint8_t len) const
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
int ArtsPrimitive::WriteUint64(int fd, const uint64_t & value,
                               uint8_t len) const
{
  uint32_t  valuePart[2];
  uint16_t  val16;
  uint8_t   val8;
  int       rc = -1;
  
  #ifdef ARTS_DEBUG_DO_ASSERTIONS
    assert(fd >= 0);
  #endif

  switch (len) {
    case 1:
      val8 = value;
      rc = this->FdWrite(fd,&val8,sizeof(val8));
      break;
    case 2:
      val16 = value;
      val16 = htons(val16);
      rc = this->FdWrite(fd,&val16,sizeof(val16));
      break;
    case 4:
      valuePart[0] = value;
      valuePart[0] = htonl(value);
      rc = this->FdWrite(fd,&valuePart[0],sizeof(uint32_t));
      break;
    case 8:
      valuePart[0] = htonl(value >> 32);
      valuePart[1] = htonl(value & 0xffffffff);
      rc = this->FdWrite(fd,valuePart,sizeof(valuePart));
      break;
    default:
      #ifdef ARTS_DEBUG_DO_ASSERTIONS
        assert((len == 1) || (len == 2) || (len == 4) || (len == 8));
      #endif
      break;
  }
  if (rc != len)
    return(-1);
  
  return(rc);
}

//-------------------------------------------------------------------------
//   istream & ArtsPrimitive::ReadUint64(istream & is, uint64_t & value,   
//                                       uint8_t len) const
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
istream & ArtsPrimitive::ReadUint64(istream & is, uint64_t & value,
                                    uint8_t len) const
{
  uint32_t  valuePart[2];
  uint16_t  val16;
  uint8_t   val8;

  switch (len) {
    case 1:
      is.read((char*)&val8,sizeof(val8));
      value = val8;
      break;
    case 2:
      is.read((char*)&val16,sizeof(val16));
      value = ntohs(val16);
      break;
    case 4:
      is.read((char*)&valuePart[0],sizeof(uint32_t));
      value = ntohl(valuePart[0]);
      break;
    case 8:
      is.read((char*)valuePart,sizeof(valuePart));
      value = ((uint64_t)ntohl(valuePart[0])) << 32;
      value += ntohl(valuePart[1]);
      break;
    default:
      #ifdef ARTS_DEBUG_DO_ASSERTIONS
        assert((len == 1) || (len == 2) || (len == 4) || (len == 8));
      #endif
      break;
  }

  return(is);
}

//-------------------------------------------------------------------------
//       int ArtsPrimitive::ReadUint64(int fd, uint64_t & value,         
//                                     uint8_t len) const
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
int ArtsPrimitive::ReadUint64(int fd, uint64_t & value,
                              uint8_t len) const
{
  uint32_t  valuePart[2];
  uint16_t  val16;
  uint8_t   val8;
  int       rc = -1;
  
  #ifdef ARTS_DEBUG_DO_ASSERTIONS
    assert(fd >= 0);
  #endif

  switch (len) {
    case 1:
      rc = this->FdRead(fd,&val8,sizeof(val8));
      value = val8;
      break;
    case 2:
      rc = this->FdRead(fd,&val16,sizeof(val16));
      value = ntohs(val16);
      break;
    case 4:
      rc = this->FdRead(fd,&valuePart[0],sizeof(uint32_t));
      value = ntohl(valuePart[0]);
      break;
    case 8:
      rc = this->FdRead(fd,valuePart,sizeof(valuePart));
      value = ((uint64_t)ntohl(valuePart[0])) << 32;
      value += ntohl(valuePart[1]);
      break;
    default:
      #ifdef ARTS_DEBUG_DO_ASSERTIONS
        assert((len == 1) || (len == 2) || (len == 4) || (len == 8));
      #endif
      break;
  }
  if (rc != len)
    return(-1);
  
  return(rc);
}

//-------------------------------------------------------------------------
//      istream & ArtsPrimitive::ReadIpv4Network(istream & is,
//                                               ipv4addr_t & value,
//                                               uint8_t len) const
//.........................................................................
//  
//-------------------------------------------------------------------------
istream & ArtsPrimitive::ReadIpv4Network(istream & is,
                                         ipv4addr_t & value,
                                         uint8_t len) const
{
  uint8_t  octet1 = 0;
  uint8_t  octet2 = 0;
  uint8_t  octet3 = 0;
  ipv4addr_t  ipAddr;
  
  switch (len) {
    case 1:
      is.read((char*)&octet1,sizeof(octet1));
      value = htonl((ipv4addr_t)octet1 << 24);
      break;
    case 2:
      is.read((char*)&octet1,sizeof(octet1));
      is.read((char*)&octet2,sizeof(octet2));
      value = htonl(((ipv4addr_t)octet1 << 24) | ((ipv4addr_t)octet2 << 16));
      break;
    case 3:
      is.read((char*)&octet1,sizeof(octet1));
      is.read((char*)&octet2,sizeof(octet2));
      is.read((char*)&octet3,sizeof(octet3));
      value = htonl(((ipv4addr_t)octet1 << 24) |
                    ((ipv4addr_t)octet2 << 16) |
                    ((ipv4addr_t)octet3 << 8));
      break;
    case 4:
      is.read((char*)&ipAddr,sizeof(ipAddr));
      value = ipAddr;
      break;
    default:
      #ifdef ARTS_DEBUG_DO_ASSERTIONS
        assert((len <= 4) && (len > 0));
      #endif
      break;
  }
  return(is);
}

//-------------------------------------------------------------------------
//      int ArtsPrimitive::ReadIpv4Network(int fd, ipv4addr_t & value,     
//                                         uint8_t len) const
//.........................................................................
//  
//-------------------------------------------------------------------------
int ArtsPrimitive::ReadIpv4Network(int fd, ipv4addr_t & value,
                                   uint8_t len) const
{
  uint8_t  octet1 = 0;
  uint8_t  octet2 = 0;
  uint8_t  octet3 = 0;
  ipv4addr_t  ipAddr;
  
  int      rc = -1;

  #ifdef ARTS_DEBUG_DO_ASSERTIONS
    assert(fd >= 0);
  #endif

  switch (len) {
    case 1:
      rc = this->FdRead(fd,&octet1,sizeof(octet1));
      value = htonl((ipv4addr_t)octet1 << 24);
      break;
    case 2:
      rc = this->FdRead(fd,&octet1,sizeof(octet1));
      rc += this->FdRead(fd,&octet2,sizeof(octet2));
      value = htonl(((ipv4addr_t)octet1 << 24) | ((ipv4addr_t)octet2 << 16));
      break;
    case 3:
      rc = this->FdRead(fd,&octet1,sizeof(octet1));
      rc += this->FdRead(fd,&octet2,sizeof(octet2));
      rc += this->FdRead(fd,&octet3,sizeof(octet3));
      value = htonl(((ipv4addr_t)octet1 << 24) |
                    ((ipv4addr_t)octet2 << 16) |
                    ((ipv4addr_t)octet3 << 8));
      break;
    case 4:
      rc = this->FdRead(fd,&ipAddr,sizeof(ipAddr));
      value = ipAddr;
      break;
    default:
      #ifdef ARTS_DEBUG_DO_ASSERTIONS
        assert((len <= 4) && (len > 0));
      #endif
      break;
  }
  return(rc);
}

//-------------------------------------------------------------------------
//   ostream & ArtsPrimitive::WriteIpv4Network(ostream & is,
//                                             const ipv4addr_t & value,
//                                             uint8_t len) const
//.........................................................................
//  
//-------------------------------------------------------------------------
ostream & ArtsPrimitive::WriteIpv4Network(ostream & os,
                                          const ipv4addr_t & value,
                                          uint8_t len) const
{
  uint8_t  octet1 = 0;
  uint8_t  octet2 = 0;
  uint8_t  octet3 = 0;
  ipv4addr_t  netaddr;

  switch (len) {
    case 1:
      octet1 = ntohl(value) >> 24;
      os.write((char*)&octet1,sizeof(octet1));
      break;
    case 2:
      netaddr = ntohl(value);
      octet1 = (ipv4addr_t)(netaddr >> 24) & 0xff;
      octet2 = (ipv4addr_t)(netaddr >> 16) & 0xff;
      os.write((char*)&octet1,sizeof(octet1));
      os.write((char*)&octet2,sizeof(octet2));
      break;
    case 3:
      netaddr = ntohl(value);
      octet1 = (ipv4addr_t)(netaddr >> 24) & 0xff;
      octet2 = (ipv4addr_t)(netaddr >> 16) & 0xff;
      octet3 = (ipv4addr_t)(netaddr >> 8) & 0xff;
      os.write((char*)&octet1,sizeof(octet1));
      os.write((char*)&octet2,sizeof(octet2));
      os.write((char*)&octet3,sizeof(octet3));
      break;
    case 4:
      os.write((char*)&value,4);
      break;
    default:
      #ifdef ARTS_DEBUG_DO_ASSERTIONS
        assert((len <= 4) && (len > 0));
      #endif
      break;
  }
  return(os);
}

//-------------------------------------------------------------------------
//  int ArtsPrimitive::WriteIpv4Network(int fd, const ipv4addr_t & value,     
//                                      uint8_t len) const
//.........................................................................
//  
//-------------------------------------------------------------------------
int ArtsPrimitive::WriteIpv4Network(int fd, const ipv4addr_t & value,
                                    uint8_t len) const
{
  uint8_t     octet1 = 0;
  uint8_t     octet2 = 0;
  uint8_t     octet3 = 0;
  int         rc = -1;
  ipv4addr_t  netaddr;

  #ifdef ARTS_DEBUG_DO_ASSERTIONS
    assert(fd >= 0);
  #endif

  switch (len) {
    case 1:
      octet1 = (ipv4addr_t)ntohl(value) >> 24;
      rc = this->FdWrite(fd,&octet1,sizeof(octet1));
      break;
    case 2:
      netaddr = ntohl(value);
      octet1 = (ipv4addr_t)(netaddr >> 24) & 0xff;
      octet2 = (ipv4addr_t)(netaddr >> 16) & 0xff;
      rc = this->FdWrite(fd,&octet1,sizeof(octet1));
      rc += this->FdWrite(fd,&octet2,sizeof(octet2));
      break;
    case 3:
      netaddr = ntohl(value);
      octet1 = (ipv4addr_t)(netaddr >> 24) & 0xff;
      octet2 = (ipv4addr_t)(netaddr >> 16) & 0xff;
      octet3 = (ipv4addr_t)(netaddr >> 8) & 0xff;
      rc = this->FdWrite(fd,&octet1,sizeof(octet1));
      rc += this->FdWrite(fd,&octet2,sizeof(octet2));
      rc += this->FdWrite(fd,&octet3,sizeof(octet3));
      break;
    case 4:
      rc = this->FdWrite(fd,&value,4);
      break;
    default:
      #ifdef ARTS_DEBUG_DO_ASSERTIONS
        assert((len <= 4) && (len > 0));
      #endif
      break;
  }
  return(rc);
}

//-------------------------------------------------------------------------
//  istream & ArtsPrimitive::ReadFloat(istream & is, float & value) const
//.........................................................................
//  
//-------------------------------------------------------------------------
istream & ArtsPrimitive::ReadFloat(istream & is, float & value) const
{
  XDR  *xdrs;
  char  buf[4];

  is.read(buf,4);
  xdrmem_create(xdrs,buf,4,XDR_DECODE);
  xdr_float(xdrs,&value);
  xdr_destroy((xdrs));
  return(is);
}


//-------------------------------------------------------------------------
//       int ArtsPrimitive::ReadFloat(int fd, float & value) const
//.........................................................................
//  
//-------------------------------------------------------------------------
int ArtsPrimitive::ReadFloat(int fd, float & value) const
{
  XDR  *xdrs;
  char  buf[4];
  int   bytesRead;

  #ifdef ARTS_DEBUG_DO_ASSERTIONS
    assert(fd >= 0);
  #endif

  bytesRead = this->FdRead(fd,buf,4);
  if (bytesRead < 4)
    return(-1);
  
  xdrmem_create(xdrs,buf,4,XDR_DECODE);
  xdr_float(xdrs,&value);
  xdr_destroy(xdrs);

  return(bytesRead);
}


//-------------------------------------------------------------------------
//  ostream & ArtsPrimitive::WriteFloat(ostream & os, float value) const
//.........................................................................
//  
//-------------------------------------------------------------------------
ostream & ArtsPrimitive::WriteFloat(ostream & os, float value) const
{
  XDR   *xdrs;
  char   buf[4];

  xdrmem_create(xdrs,buf,4,XDR_ENCODE);
  xdr_float(xdrs,&value);
  os.write(buf,4);
  xdr_destroy(xdrs);

  return(os);
}


//-------------------------------------------------------------------------
//        int ArtsPrimitive::WriteFloat(int fd, float value) const
//.........................................................................
//  
//-------------------------------------------------------------------------
int ArtsPrimitive::WriteFloat(int fd, float value) const
{
  XDR   *xdrs;
  char   buf[4];
  int    bytesWritten;

  #ifdef ARTS_DEBUG_DO_ASSERTIONS
    assert(fd >= 0);
  #endif
    
  xdrmem_create(xdrs,buf,4,XDR_ENCODE);
  xdr_float(xdrs,&value);
  bytesWritten = this->FdWrite(fd,buf,4);
  xdr_destroy(xdrs);
  
  if (bytesWritten < 4)
    return(-1);

  return(bytesWritten);
}

//-------------------------------------------------------------------------
//  istream & ArtsPrimitive::ReadDouble(istream & is, double & value) const
//.........................................................................
//  
//-------------------------------------------------------------------------
istream & ArtsPrimitive::ReadDouble(istream & is, double & value) const
{
  XDR  *xdrs;
  char  buf[8];

  is.read(buf,8);
  xdrmem_create(xdrs,buf,8,XDR_DECODE);
  xdr_double(xdrs,&value);
  xdr_destroy(xdrs);
  return(is);
}


//-------------------------------------------------------------------------
//       int ArtsPrimitive::ReadDouble(int fd, double & value) const
//.........................................................................
//  
//-------------------------------------------------------------------------
int ArtsPrimitive::ReadDouble(int fd, double & value) const
{
  XDR  *xdrs;
  char  buf[8];
  int   bytesRead;

  #ifdef ARTS_DEBUG_DO_ASSERTIONS
    assert(fd >= 0);
  #endif

  bytesRead = this->FdRead(fd,buf,8);
  if (bytesRead < 8)
    return(-1);
  
  xdrmem_create(xdrs,buf,8,XDR_DECODE);
  xdr_double(xdrs,&value);
  xdr_destroy(xdrs);

  return(bytesRead);
}


//-------------------------------------------------------------------------
//  ostream & ArtsPrimitive::WriteDouble(ostream & os, double value) const
//.........................................................................
//  
//-------------------------------------------------------------------------
ostream & ArtsPrimitive::WriteDouble(ostream & os, double value) const
{
  XDR   *xdrs;
  char   buf[8];

  xdrmem_create(xdrs,buf,8,XDR_ENCODE);
  xdr_double(xdrs,&value);
  os.write(buf,8);
  xdr_destroy(xdrs);

  return(os);
}


//-------------------------------------------------------------------------
//        int ArtsPrimitive::WriteDouble(int fd, double value) const
//.........................................................................
//  
//-------------------------------------------------------------------------
int ArtsPrimitive::WriteDouble(int fd, double value) const
{
  XDR   *xdrs;
  char   buf[8];
  int    bytesWritten;

  #ifdef ARTS_DEBUG_DO_ASSERTIONS
    assert(fd >= 0);
  #endif
    
  xdrmem_create(xdrs,buf,8,XDR_ENCODE);
  xdr_double(xdrs,&value);
  bytesWritten = this->FdWrite(fd,buf,8);
  xdr_destroy(xdrs);
  
  if (bytesWritten < 8)
    return(-1);

  return(bytesWritten);
}

ArtsPrimitive  g_ArtsLibInternal_Primitive;
