<commit_before>// Copyright (c) 2006- Facebook
// Distributed under the Thrift Software License
//
// See accompanying file LICENSE or visit the Thrift site at:
// http://developers.facebook.com/thrift/

#include "TBinaryProtocol.h"

#include <boost/static_assert.hpp>

using std::string;

// Use this to get around strict aliasing rules.
// For example, uint64_t i = bitwise_cast<uint64_t>(returns_double());
// The most obvious implementation is to just cast a pointer,
// but that doesn't work.
// For a pretty in-depth explanation of the problem, see
// http://www.cellperformance.com/mike_acton/2006/06/ (...)
// understanding_strict_aliasing.html
template <typename To, typename From>
static inline To bitwise_cast(From from) {
  BOOST_STATIC_ASSERT(sizeof(From) == sizeof(To));

  // BAD!!!  These are all broken with -O2.
  //return *reinterpret_cast<To*>(&from);  // BAD!!!
  //return *static_cast<To*>(static_cast<void*>(&from));  // BAD!!!
  //return *(To*)(void*)&from;  // BAD!!!

  // Super clean and paritally blessed by section 3.9 of the standard.
  //unsigned char c[sizeof(from)];
  //memcpy(c, &from, sizeof(from));
  //To to;
  //memcpy(&to, c, sizeof(c));
  //return to;

  // Slightly more questionable.
  // Same code emitted by GCC.
  //To to;
  //memcpy(&to, &from, sizeof(from));
  //return to;

  // Technically undefined, but almost universally supported,
  // and the most efficient implementation.
  union {
    From f;
    To t;
  } u;
  u.f = from;
  return u.t;
}

namespace facebook { namespace thrift { namespace protocol {

uint32_t TBinaryProtocol::writeMessageBegin(const std::string& name,
                                            const TMessageType messageType,
                                            const int32_t seqid) {
  if (strict_write_) {
    int32_t version = (VERSION_1) | ((int32_t)messageType);
    uint32_t wsize = 0;
    wsize += writeI32(version);
    wsize += writeString(name);
    wsize += writeI32(seqid);
    return wsize;
  } else {
    uint32_t wsize = 0;
    wsize += writeString(name);
    wsize += writeByte((int8_t)messageType);
    wsize += writeI32(seqid);
    return wsize;
  }
}

uint32_t TBinaryProtocol::writeMessageEnd() {
  return 0;
}

uint32_t TBinaryProtocol::writeStructBegin(const string& name) {
  return 0;
}

uint32_t TBinaryProtocol::writeStructEnd() {
  return 0;
}

uint32_t TBinaryProtocol::writeFieldBegin(const string& name,
                                          const TType fieldType,
                                          const int16_t fieldId) {
  uint32_t wsize = 0;
  wsize += writeByte((int8_t)fieldType);
  wsize += writeI16(fieldId);
  return wsize;
}

uint32_t TBinaryProtocol::writeFieldEnd() {
  return 0;
}

uint32_t TBinaryProtocol::writeFieldStop() {
  return
    writeByte((int8_t)T_STOP);
}

uint32_t TBinaryProtocol::writeMapBegin(const TType keyType,
                                        const TType valType,
                                        const uint32_t size) {
  uint32_t wsize = 0;
  wsize += writeByte((int8_t)keyType);
  wsize += writeByte((int8_t)valType);
  wsize += writeI32((int32_t)size);
  return wsize;
}

uint32_t TBinaryProtocol::writeMapEnd() {
  return 0;
}

uint32_t TBinaryProtocol::writeListBegin(const TType elemType,
                                         const uint32_t size) {
  uint32_t wsize = 0;
  wsize += writeByte((int8_t) elemType);
  wsize += writeI32((int32_t)size);
  return wsize;
}

uint32_t TBinaryProtocol::writeListEnd() {
  return 0;
}

uint32_t TBinaryProtocol::writeSetBegin(const TType elemType,
                                        const uint32_t size) {
  uint32_t wsize = 0;
  wsize += writeByte((int8_t)elemType);
  wsize += writeI32((int32_t)size);
  return wsize;
}

uint32_t TBinaryProtocol::writeSetEnd() {
  return 0;
}

uint32_t TBinaryProtocol::writeBool(const bool value) {
  uint8_t tmp =  value ? 1 : 0;
  trans_->write(&tmp, 1);
  return 1;
}

uint32_t TBinaryProtocol::writeByte(const int8_t byte) {
  trans_->write((uint8_t*)&byte, 1);
  return 1;
}

uint32_t TBinaryProtocol::writeI16(const int16_t i16) {
  int16_t net = (int16_t)htons(i16);
  trans_->write((uint8_t*)&net, 2);
  return 2;
}

uint32_t TBinaryProtocol::writeI32(const int32_t i32) {
  int32_t net = (int32_t)htonl(i32);
  trans_->write((uint8_t*)&net, 4);
  return 4;
}

uint32_t TBinaryProtocol::writeI64(const int64_t i64) {
  int64_t net = (int64_t)htonll(i64);
  trans_->write((uint8_t*)&net, 8);
  return 8;
}

uint32_t TBinaryProtocol::writeDouble(const double dub) {
  BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t));
  BOOST_STATIC_ASSERT(std::numeric_limits<double>::is_iec559);

  uint64_t bits = bitwise_cast<uint64_t>(dub);
  bits = htonll(bits);
  trans_->write((uint8_t*)&bits, 8);
  return 8;
}

uint32_t TBinaryProtocol::writeString(const string& str) {
  uint32_t size = str.size();
  uint32_t result = writeI32((int32_t)size);
  if (size > 0) {
    trans_->write((uint8_t*)str.data(), size);
  }
  return result + size;
}

uint32_t TBinaryProtocol::writeBinary(const string& str) {
  return TBinaryProtocol::writeString(str);
}

/**
 * Reading functions
 */

uint32_t TBinaryProtocol::readMessageBegin(std::string& name,
                                           TMessageType& messageType,
                                           int32_t& seqid) {
  uint32_t result = 0;
  int32_t sz;
  result += readI32(sz);

  if (sz < 0) {
    // Check for correct version number
    int32_t version = sz & VERSION_MASK;
    if (version != VERSION_1) {
      throw TProtocolException(TProtocolException::BAD_VERSION, "Bad version identifier");
    }
    messageType = (TMessageType)(sz & 0x000000ff);
    result += readString(name);
    result += readI32(seqid);
  } else {
    if (strict_read_) {
      throw TProtocolException(TProtocolException::BAD_VERSION, "No version identifier... old protocol client in strict mode?");
    } else {
      // Handle pre-versioned input
      int8_t type;
      result += readStringBody(name, sz);
      result += readByte(type);
      messageType = (TMessageType)type;
      result += readI32(seqid);
    }
  }
  return result;
}

uint32_t TBinaryProtocol::readMessageEnd() {
  return 0;
}

uint32_t TBinaryProtocol::readStructBegin(string& name) {
  name = "";
  return 0;
}

uint32_t TBinaryProtocol::readStructEnd() {
  return 0;
}

uint32_t TBinaryProtocol::readFieldBegin(string& name,
                                         TType& fieldType,
                                         int16_t& fieldId) {
  uint32_t result = 0;
  int8_t type;
  result += readByte(type);
  fieldType = (TType)type;
  if (fieldType == T_STOP) {
    fieldId = 0;
    return result;
  }
  result += readI16(fieldId);
  return result;
}

uint32_t TBinaryProtocol::readFieldEnd() {
  return 0;
}

uint32_t TBinaryProtocol::readMapBegin(TType& keyType,
                                       TType& valType,
                                       uint32_t& size) {
  int8_t k, v;
  uint32_t result = 0;
  int32_t sizei;
  result += readByte(k);
  keyType = (TType)k;
  result += readByte(v);
  valType = (TType)v;
  result += readI32(sizei);
  if (sizei < 0) {
    throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
  } else if (container_limit_ && sizei > container_limit_) {
    throw TProtocolException(TProtocolException::SIZE_LIMIT);
  }
  size = (uint32_t)sizei;
  return result;
}

uint32_t TBinaryProtocol::readMapEnd() {
  return 0;
}

uint32_t TBinaryProtocol::readListBegin(TType& elemType,
                                        uint32_t& size) {
  int8_t e;
  uint32_t result = 0;
  int32_t sizei;
  result += readByte(e);
  elemType = (TType)e;
  result += readI32(sizei);
  if (sizei < 0) {
    throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
  } else if (container_limit_ && sizei > container_limit_) {
    throw TProtocolException(TProtocolException::SIZE_LIMIT);
  }
  size = (uint32_t)sizei;
  return result;
}

uint32_t TBinaryProtocol::readListEnd() {
  return 0;
}

uint32_t TBinaryProtocol::readSetBegin(TType& elemType,
                                       uint32_t& size) {
  int8_t e;
  uint32_t result = 0;
  int32_t sizei;
  result += readByte(e);
  elemType = (TType)e;
  result += readI32(sizei);
  if (sizei < 0) {
    throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
  } else if (container_limit_ && sizei > container_limit_) {
    throw TProtocolException(TProtocolException::SIZE_LIMIT);
  }
  size = (uint32_t)sizei;
  return result;
}

uint32_t TBinaryProtocol::readSetEnd() {
  return 0;
}

uint32_t TBinaryProtocol::readBool(bool& value) {
  uint8_t b[1];
  trans_->readAll(b, 1);
  value = *(int8_t*)b != 0;
  return 1;
}

uint32_t TBinaryProtocol::readByte(int8_t& byte) {
  uint8_t b[1];
  trans_->readAll(b, 1);
  byte = *(int8_t*)b;
  return 1;
}

uint32_t TBinaryProtocol::readI16(int16_t& i16) {
  uint8_t b[2];
  trans_->readAll(b, 2);
  i16 = *(int16_t*)b;
  i16 = (int16_t)ntohs(i16);
  return 2;
}

uint32_t TBinaryProtocol::readI32(int32_t& i32) {
  uint8_t b[4];
  trans_->readAll(b, 4);
  i32 = *(int32_t*)b;
  i32 = (int32_t)ntohl(i32);
  return 4;
}

uint32_t TBinaryProtocol::readI64(int64_t& i64) {
  uint8_t b[8];
  trans_->readAll(b, 8);
  i64 = *(int64_t*)b;
  i64 = (int64_t)ntohll(i64);
  return 8;
}

uint32_t TBinaryProtocol::readDouble(double& dub) {
  BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t));
  BOOST_STATIC_ASSERT(std::numeric_limits<double>::is_iec559);

  uint64_t bits;
  uint8_t b[8];
  trans_->readAll(b, 8);
  bits = *(uint64_t*)b;
  bits = ntohll(bits);
  dub = bitwise_cast<double>(bits);
  return 8;
}

uint32_t TBinaryProtocol::readString(string& str) {
  uint32_t result;
  int32_t size;
  result = readI32(size);
  return result + readStringBody(str, size);
}

uint32_t TBinaryProtocol::readBinary(string& str) {
  return TBinaryProtocol::readString(str);
}

uint32_t TBinaryProtocol::readStringBody(string& str, int32_t size) {
  uint32_t result = 0;

  // Catch error cases
  if (size < 0) {
    throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
  }
  if (string_limit_ > 0 && size > string_limit_) {
    throw TProtocolException(TProtocolException::SIZE_LIMIT);
  }

  // Catch empty string case
  if (size == 0) {
    str = "";
    return result;
  }

  // Use the heap here to prevent stack overflow for v. large strings
  if (size > string_buf_size_ || string_buf_ == NULL) {
    string_buf_ = (uint8_t*)std::realloc(string_buf_, (uint32_t)size);
    if (string_buf_ == NULL) {
      string_buf_size_ = 0;
      throw TProtocolException(TProtocolException::UNKNOWN, "Out of memory in TBinaryProtocol::readString");
    }
    string_buf_size_ = size;
  }
  trans_->readAll(string_buf_, size);
  str = string((char*)string_buf_, size);
  return (uint32_t)size;
}

}}} // facebook::thrift::protocol
<commit_msg>Fix a memory leak in TBinaryProtocol.<commit_after>// Copyright (c) 2006- Facebook
// Distributed under the Thrift Software License
//
// See accompanying file LICENSE or visit the Thrift site at:
// http://developers.facebook.com/thrift/

#include "TBinaryProtocol.h"

#include <boost/static_assert.hpp>

using std::string;

// Use this to get around strict aliasing rules.
// For example, uint64_t i = bitwise_cast<uint64_t>(returns_double());
// The most obvious implementation is to just cast a pointer,
// but that doesn't work.
// For a pretty in-depth explanation of the problem, see
// http://www.cellperformance.com/mike_acton/2006/06/ (...)
// understanding_strict_aliasing.html
template <typename To, typename From>
static inline To bitwise_cast(From from) {
  BOOST_STATIC_ASSERT(sizeof(From) == sizeof(To));

  // BAD!!!  These are all broken with -O2.
  //return *reinterpret_cast<To*>(&from);  // BAD!!!
  //return *static_cast<To*>(static_cast<void*>(&from));  // BAD!!!
  //return *(To*)(void*)&from;  // BAD!!!

  // Super clean and paritally blessed by section 3.9 of the standard.
  //unsigned char c[sizeof(from)];
  //memcpy(c, &from, sizeof(from));
  //To to;
  //memcpy(&to, c, sizeof(c));
  //return to;

  // Slightly more questionable.
  // Same code emitted by GCC.
  //To to;
  //memcpy(&to, &from, sizeof(from));
  //return to;

  // Technically undefined, but almost universally supported,
  // and the most efficient implementation.
  union {
    From f;
    To t;
  } u;
  u.f = from;
  return u.t;
}

namespace facebook { namespace thrift { namespace protocol {

uint32_t TBinaryProtocol::writeMessageBegin(const std::string& name,
                                            const TMessageType messageType,
                                            const int32_t seqid) {
  if (strict_write_) {
    int32_t version = (VERSION_1) | ((int32_t)messageType);
    uint32_t wsize = 0;
    wsize += writeI32(version);
    wsize += writeString(name);
    wsize += writeI32(seqid);
    return wsize;
  } else {
    uint32_t wsize = 0;
    wsize += writeString(name);
    wsize += writeByte((int8_t)messageType);
    wsize += writeI32(seqid);
    return wsize;
  }
}

uint32_t TBinaryProtocol::writeMessageEnd() {
  return 0;
}

uint32_t TBinaryProtocol::writeStructBegin(const string& name) {
  return 0;
}

uint32_t TBinaryProtocol::writeStructEnd() {
  return 0;
}

uint32_t TBinaryProtocol::writeFieldBegin(const string& name,
                                          const TType fieldType,
                                          const int16_t fieldId) {
  uint32_t wsize = 0;
  wsize += writeByte((int8_t)fieldType);
  wsize += writeI16(fieldId);
  return wsize;
}

uint32_t TBinaryProtocol::writeFieldEnd() {
  return 0;
}

uint32_t TBinaryProtocol::writeFieldStop() {
  return
    writeByte((int8_t)T_STOP);
}

uint32_t TBinaryProtocol::writeMapBegin(const TType keyType,
                                        const TType valType,
                                        const uint32_t size) {
  uint32_t wsize = 0;
  wsize += writeByte((int8_t)keyType);
  wsize += writeByte((int8_t)valType);
  wsize += writeI32((int32_t)size);
  return wsize;
}

uint32_t TBinaryProtocol::writeMapEnd() {
  return 0;
}

uint32_t TBinaryProtocol::writeListBegin(const TType elemType,
                                         const uint32_t size) {
  uint32_t wsize = 0;
  wsize += writeByte((int8_t) elemType);
  wsize += writeI32((int32_t)size);
  return wsize;
}

uint32_t TBinaryProtocol::writeListEnd() {
  return 0;
}

uint32_t TBinaryProtocol::writeSetBegin(const TType elemType,
                                        const uint32_t size) {
  uint32_t wsize = 0;
  wsize += writeByte((int8_t)elemType);
  wsize += writeI32((int32_t)size);
  return wsize;
}

uint32_t TBinaryProtocol::writeSetEnd() {
  return 0;
}

uint32_t TBinaryProtocol::writeBool(const bool value) {
  uint8_t tmp =  value ? 1 : 0;
  trans_->write(&tmp, 1);
  return 1;
}

uint32_t TBinaryProtocol::writeByte(const int8_t byte) {
  trans_->write((uint8_t*)&byte, 1);
  return 1;
}

uint32_t TBinaryProtocol::writeI16(const int16_t i16) {
  int16_t net = (int16_t)htons(i16);
  trans_->write((uint8_t*)&net, 2);
  return 2;
}

uint32_t TBinaryProtocol::writeI32(const int32_t i32) {
  int32_t net = (int32_t)htonl(i32);
  trans_->write((uint8_t*)&net, 4);
  return 4;
}

uint32_t TBinaryProtocol::writeI64(const int64_t i64) {
  int64_t net = (int64_t)htonll(i64);
  trans_->write((uint8_t*)&net, 8);
  return 8;
}

uint32_t TBinaryProtocol::writeDouble(const double dub) {
  BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t));
  BOOST_STATIC_ASSERT(std::numeric_limits<double>::is_iec559);

  uint64_t bits = bitwise_cast<uint64_t>(dub);
  bits = htonll(bits);
  trans_->write((uint8_t*)&bits, 8);
  return 8;
}

uint32_t TBinaryProtocol::writeString(const string& str) {
  uint32_t size = str.size();
  uint32_t result = writeI32((int32_t)size);
  if (size > 0) {
    trans_->write((uint8_t*)str.data(), size);
  }
  return result + size;
}

uint32_t TBinaryProtocol::writeBinary(const string& str) {
  return TBinaryProtocol::writeString(str);
}

/**
 * Reading functions
 */

uint32_t TBinaryProtocol::readMessageBegin(std::string& name,
                                           TMessageType& messageType,
                                           int32_t& seqid) {
  uint32_t result = 0;
  int32_t sz;
  result += readI32(sz);

  if (sz < 0) {
    // Check for correct version number
    int32_t version = sz & VERSION_MASK;
    if (version != VERSION_1) {
      throw TProtocolException(TProtocolException::BAD_VERSION, "Bad version identifier");
    }
    messageType = (TMessageType)(sz & 0x000000ff);
    result += readString(name);
    result += readI32(seqid);
  } else {
    if (strict_read_) {
      throw TProtocolException(TProtocolException::BAD_VERSION, "No version identifier... old protocol client in strict mode?");
    } else {
      // Handle pre-versioned input
      int8_t type;
      result += readStringBody(name, sz);
      result += readByte(type);
      messageType = (TMessageType)type;
      result += readI32(seqid);
    }
  }
  return result;
}

uint32_t TBinaryProtocol::readMessageEnd() {
  return 0;
}

uint32_t TBinaryProtocol::readStructBegin(string& name) {
  name = "";
  return 0;
}

uint32_t TBinaryProtocol::readStructEnd() {
  return 0;
}

uint32_t TBinaryProtocol::readFieldBegin(string& name,
                                         TType& fieldType,
                                         int16_t& fieldId) {
  uint32_t result = 0;
  int8_t type;
  result += readByte(type);
  fieldType = (TType)type;
  if (fieldType == T_STOP) {
    fieldId = 0;
    return result;
  }
  result += readI16(fieldId);
  return result;
}

uint32_t TBinaryProtocol::readFieldEnd() {
  return 0;
}

uint32_t TBinaryProtocol::readMapBegin(TType& keyType,
                                       TType& valType,
                                       uint32_t& size) {
  int8_t k, v;
  uint32_t result = 0;
  int32_t sizei;
  result += readByte(k);
  keyType = (TType)k;
  result += readByte(v);
  valType = (TType)v;
  result += readI32(sizei);
  if (sizei < 0) {
    throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
  } else if (container_limit_ && sizei > container_limit_) {
    throw TProtocolException(TProtocolException::SIZE_LIMIT);
  }
  size = (uint32_t)sizei;
  return result;
}

uint32_t TBinaryProtocol::readMapEnd() {
  return 0;
}

uint32_t TBinaryProtocol::readListBegin(TType& elemType,
                                        uint32_t& size) {
  int8_t e;
  uint32_t result = 0;
  int32_t sizei;
  result += readByte(e);
  elemType = (TType)e;
  result += readI32(sizei);
  if (sizei < 0) {
    throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
  } else if (container_limit_ && sizei > container_limit_) {
    throw TProtocolException(TProtocolException::SIZE_LIMIT);
  }
  size = (uint32_t)sizei;
  return result;
}

uint32_t TBinaryProtocol::readListEnd() {
  return 0;
}

uint32_t TBinaryProtocol::readSetBegin(TType& elemType,
                                       uint32_t& size) {
  int8_t e;
  uint32_t result = 0;
  int32_t sizei;
  result += readByte(e);
  elemType = (TType)e;
  result += readI32(sizei);
  if (sizei < 0) {
    throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
  } else if (container_limit_ && sizei > container_limit_) {
    throw TProtocolException(TProtocolException::SIZE_LIMIT);
  }
  size = (uint32_t)sizei;
  return result;
}

uint32_t TBinaryProtocol::readSetEnd() {
  return 0;
}

uint32_t TBinaryProtocol::readBool(bool& value) {
  uint8_t b[1];
  trans_->readAll(b, 1);
  value = *(int8_t*)b != 0;
  return 1;
}

uint32_t TBinaryProtocol::readByte(int8_t& byte) {
  uint8_t b[1];
  trans_->readAll(b, 1);
  byte = *(int8_t*)b;
  return 1;
}

uint32_t TBinaryProtocol::readI16(int16_t& i16) {
  uint8_t b[2];
  trans_->readAll(b, 2);
  i16 = *(int16_t*)b;
  i16 = (int16_t)ntohs(i16);
  return 2;
}

uint32_t TBinaryProtocol::readI32(int32_t& i32) {
  uint8_t b[4];
  trans_->readAll(b, 4);
  i32 = *(int32_t*)b;
  i32 = (int32_t)ntohl(i32);
  return 4;
}

uint32_t TBinaryProtocol::readI64(int64_t& i64) {
  uint8_t b[8];
  trans_->readAll(b, 8);
  i64 = *(int64_t*)b;
  i64 = (int64_t)ntohll(i64);
  return 8;
}

uint32_t TBinaryProtocol::readDouble(double& dub) {
  BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t));
  BOOST_STATIC_ASSERT(std::numeric_limits<double>::is_iec559);

  uint64_t bits;
  uint8_t b[8];
  trans_->readAll(b, 8);
  bits = *(uint64_t*)b;
  bits = ntohll(bits);
  dub = bitwise_cast<double>(bits);
  return 8;
}

uint32_t TBinaryProtocol::readString(string& str) {
  uint32_t result;
  int32_t size;
  result = readI32(size);
  return result + readStringBody(str, size);
}

uint32_t TBinaryProtocol::readBinary(string& str) {
  return TBinaryProtocol::readString(str);
}

uint32_t TBinaryProtocol::readStringBody(string& str, int32_t size) {
  uint32_t result = 0;

  // Catch error cases
  if (size < 0) {
    throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
  }
  if (string_limit_ > 0 && size > string_limit_) {
    throw TProtocolException(TProtocolException::SIZE_LIMIT);
  }

  // Catch empty string case
  if (size == 0) {
    str = "";
    return result;
  }

  // Use the heap here to prevent stack overflow for v. large strings
  if (size > string_buf_size_ || string_buf_ == NULL) {
    void* new_string_buf = std::realloc(string_buf_, (uint32_t)size);
    if (new_string_buf == NULL) {
      throw TProtocolException(TProtocolException::UNKNOWN, "Out of memory in TBinaryProtocol::readString");
    }
    string_buf_ = (uint8_t*)new_string_buf;
    string_buf_size_ = size;
  }
  trans_->readAll(string_buf_, size);
  str = string((char*)string_buf_, size);
  return (uint32_t)size;
}

}}} // facebook::thrift::protocol
<|endoftext|>


<commit_before>/*******************************************************************************
 *
 * MIT License
 *
 * Copyright (c) 2017 Advanced Micro Devices, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 *******************************************************************************/
#ifndef GUARD_VERIFY_HPP
#define GUARD_VERIFY_HPP

#include <algorithm>
#include <cmath>
#include <functional>
#include <iostream>
#include <miopen/float_equal.hpp>
#include <miopen/returns.hpp>
#include <numeric>

namespace miopen {

// Compute the value of a range
template <class R>
using range_value = typename std::decay<decltype(*std::declval<R>().begin())>::type;

struct sum_fn
{
    template <class T, class U>
    auto operator()(T x, U y) const MIOPEN_RETURNS(x + y);
};
static constexpr sum_fn sum{};

struct max_fn
{
    template <class T, class U>
    auto operator()(T x, U y) const MIOPEN_RETURNS(x > y ? x : y);
};
static constexpr max_fn max{};

struct abs_diff_fn
{
    template <class T, class U>
    auto operator()(T x, U y) const MIOPEN_RETURNS(std::fabs(x - y));
};

static constexpr abs_diff_fn abs_diff{};

struct not_finite_fn
{
    template <class T>
    bool operator()(T x) const
    {
        return not std::isfinite(x);
    }
};
static constexpr not_finite_fn not_finite{};

template <class T, class U>
T as(T, U x)
{
    return x;
}

struct compare_mag_fn
{
    template <class T, class U>
    bool operator()(T x, U y) const
    {
        return std::fabs(x) < std::fabs(y);
    }
};
static constexpr compare_mag_fn compare_mag{};

struct square_diff_fn
{
    template <class T, class U>
    double operator()(T x, U y) const
    {
        return (x - y) * (x - y);
    }
};
static constexpr square_diff_fn square_diff{};

template <class R1>
bool range_empty(R1&& r1)
{
    return r1.begin() == r1.end();
}

template <class R1>
auto range_distance(R1&& r1) MIOPEN_RETURNS(std::distance(r1.begin(), r1.end()));

template <class R1>
bool range_zero(R1&& r1)
{
    return std::all_of(r1.begin(), r1.end(), [](float x) { return x == 0.0; });
}

template <class R1, class R2, class T, class Reducer, class Product>
T range_product(R1&& r1, R2&& r2, T state, Reducer r, Product p)
{
    return std::inner_product(r1.begin(), r1.end(), r2.begin(), state, r, p);
}

template <class R1, class R2, class Compare>
std::size_t mismatch_idx(R1&& r1, R2&& r2, Compare compare)
{
    auto p = std::mismatch(r1.begin(), r1.end(), r2.begin(), compare);
    return std::distance(r1.begin(), p.first);
}

template <class R1, class Predicate>
long find_idx(R1&& r1, Predicate p)
{
    auto it = std::find_if(r1.begin(), r1.end(), p);
    if(it == r1.end())
        return -1;
    else
        return std::distance(r1.begin(), it);
}

template <class R1, class R2>
double max_diff(R1&& r1, R2&& r2)
{
    return range_product(r1, r2, 0.0, max, abs_diff);
}

template <class R1, class R2, class T>
std::size_t mismatch_diff(R1&& r1, R2&& r2, T diff)
{
    return mismatch_idx(
        r1,
        r2,
        std::bind(
            float_equal, diff, std::bind(abs_diff, std::placeholders::_1, std::placeholders::_2)));
}

template <class R1, class R2>
double rms_range(R1&& r1, R2&& r2)
{
    std::size_t n = range_distance(r1);
    if(n == range_distance(r2))
    {
        double square_difference = range_product(r1, r2, 0.0, sum_fn{}, square_diff);
        double mag1              = *std::max_element(r1.begin(), r1.end(), compare_mag);
        double mag2              = *std::max_element(r2.begin(), r2.end(), compare_mag);
        double mag =
            std::max({std::fabs(mag1), std::fabs(mag2), std::numeric_limits<double>::min()});
        return std::sqrt(square_difference) / (std::sqrt(n) * mag);
    }
    else
        return std::numeric_limits<range_value<R1>>::max();
}
}

#endif
<commit_msg>Fix stack address problem<commit_after>/*******************************************************************************
 *
 * MIT License
 *
 * Copyright (c) 2017 Advanced Micro Devices, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 *******************************************************************************/
#ifndef GUARD_VERIFY_HPP
#define GUARD_VERIFY_HPP

#include <algorithm>
#include <cmath>
#include <functional>
#include <iostream>
#include <miopen/float_equal.hpp>
#include <miopen/returns.hpp>
#include <numeric>

namespace miopen {

// Compute the value of a range
template <class R>
using range_value = typename std::decay<decltype(*std::declval<R>().begin())>::type;

struct sum_fn
{
    template <class T, class U>
    auto operator()(T x, U y) const MIOPEN_RETURNS(x + y);
};
static constexpr sum_fn sum{};

struct max_fn
{
    template<class T>
    static T id(T x) { return x; }

    template <class T, class U>
    auto operator()(T x, U y) const MIOPEN_RETURNS(max_fn::id(x > y ? x : y));
};
static constexpr max_fn max{};

struct abs_diff_fn
{
    template <class T, class U>
    auto operator()(T x, U y) const MIOPEN_RETURNS(std::fabs(x - y));
};

static constexpr abs_diff_fn abs_diff{};

struct not_finite_fn
{
    template <class T>
    bool operator()(T x) const
    {
        return not std::isfinite(x);
    }
};
static constexpr not_finite_fn not_finite{};

template <class T, class U>
T as(T, U x)
{
    return x;
}

struct compare_mag_fn
{
    template <class T, class U>
    bool operator()(T x, U y) const
    {
        return std::fabs(x) < std::fabs(y);
    }
};
static constexpr compare_mag_fn compare_mag{};

struct square_diff_fn
{
    template <class T, class U>
    double operator()(T x, U y) const
    {
        return (x - y) * (x - y);
    }
};
static constexpr square_diff_fn square_diff{};

template <class R1>
bool range_empty(R1&& r1)
{
    return r1.begin() == r1.end();
}

template <class R1>
auto range_distance(R1&& r1) MIOPEN_RETURNS(std::distance(r1.begin(), r1.end()));

template <class R1>
bool range_zero(R1&& r1)
{
    return std::all_of(r1.begin(), r1.end(), [](float x) { return x == 0.0; });
}

template <class R1, class R2, class T, class Reducer, class Product>
T range_product(R1&& r1, R2&& r2, T state, Reducer r, Product p)
{
    return std::inner_product(r1.begin(), r1.end(), r2.begin(), state, r, p);
}

template <class R1, class R2, class Compare>
std::size_t mismatch_idx(R1&& r1, R2&& r2, Compare compare)
{
    auto p = std::mismatch(r1.begin(), r1.end(), r2.begin(), compare);
    return std::distance(r1.begin(), p.first);
}

template <class R1, class Predicate>
long find_idx(R1&& r1, Predicate p)
{
    auto it = std::find_if(r1.begin(), r1.end(), p);
    if(it == r1.end())
        return -1;
    else
        return std::distance(r1.begin(), it);
}

template <class R1, class R2>
double max_diff(R1&& r1, R2&& r2)
{
    return range_product(r1, r2, 0.0, max, abs_diff);
}

template <class R1, class R2, class T>
std::size_t mismatch_diff(R1&& r1, R2&& r2, T diff)
{
    return mismatch_idx(
        r1,
        r2,
        std::bind(
            float_equal, diff, std::bind(abs_diff, std::placeholders::_1, std::placeholders::_2)));
}

template <class R1, class R2>
double rms_range(R1&& r1, R2&& r2)
{
    std::size_t n = range_distance(r1);
    if(n == range_distance(r2))
    {
        double square_difference = range_product(r1, r2, 0.0, sum_fn{}, square_diff);
        double mag1              = *std::max_element(r1.begin(), r1.end(), compare_mag);
        double mag2              = *std::max_element(r2.begin(), r2.end(), compare_mag);
        double mag =
            std::max({std::fabs(mag1), std::fabs(mag2), std::numeric_limits<double>::min()});
        return std::sqrt(square_difference) / (std::sqrt(n) * mag);
    }
    else
        return std::numeric_limits<range_value<R1>>::max();
}
}

#endif
<|endoftext|>


<commit_before>/*
 * A little test program for md5 code which does a md5 on all the
 * bytes sent to stdin.
 */

#include <string.h>
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <vector>

#include "../src/md5.h"

/*
 * Print a signature
 */
static void print_sig(const unsigned char *sig) {
    const unsigned char* sig_p;

    for (sig_p = sig; sig_p < sig + MD5_SIZE; sig_p++) {
        (void)printf("%02x", *sig_p);
    }
}

/*
 * Read in from stdin and run MD5 on the input
 */
static void read_file(const char* filename) {
    unsigned char sig[MD5_SIZE];
    char buffer[4096];
    md5::md5_t md5;
    bool useCin;
    std::ifstream file;

    if (filename[0] == '-') {
        useCin = true;
    } else {
        useCin = false;
        file.open(filename, std::ios::binary);
        if (!file.is_open()) {
            std::cerr << "failed to open file " << filename << std::endl;
            exit(1);
        }
    }

    /* iterate over file */
    if (useCin) {
        const char* input = filename + 1;
        std::cout << "Processing: '" << input << "'\n";
        md5.process(input, strlen(input));
    } else {
        do {
            file.read(buffer, 4096);
            md5.process(buffer, file.gcount());
        } while (file);
    }

    md5.finish(sig);

    (void)printf("%25s '", "Resulting signature:");
    print_sig(sig);
    (void)printf("'\n");

    /* convert to string to print */
    md5::sig_to_string(sig, buffer, sizeof(buffer));
    (void)printf("%25s '%s'\n", "Results of md5_to_string:", buffer);

    /* now we convert it from string back into the sig */
    md5::sig_from_string(sig, buffer);

    (void)printf("%25s '", "After md5_from_string:");
    print_sig(sig);
    (void)printf("'\n");
}

static void run_tests(void)
{
    unsigned char sig[MD5_SIZE], sig2[MD5_SIZE];
    char str[MD5_STRING_SIZE];

  /* MD5 Test Suite from RFC1321 */
    std::vector<std::pair<const char*, const char*> > tests;
    tests.push_back(std::pair<const char*, const char*>("", "d41d8cd98f00b204e9800998ecf8427e"));
    tests.push_back(std::pair<const char*, const char*>("a", "0cc175b9c0f1b6a831c399e269772661"));
    tests.push_back(std::pair<const char*, const char*>("abc", "900150983cd24fb0d6963f7d28e17f72"));
    tests.push_back(std::pair<const char*, const char*>("message digest", "f96b697d7cb7938d525a2f31aaf161d0"));
    tests.push_back(std::pair<const char*, const char*>("abcdefghijklmnopqrstuvwxyz", "c3fcd3d76192e4007dfb496cca67e13b"));
    tests.push_back(std::pair<const char*, const char*>("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "d174ab98d277d9f5a5611c2c9f419d9f"));
    tests.push_back(std::pair<const char*, const char*>("12345678901234567890123456789012345678901234567890123456789012345678901234567890", "57edf4a22be3c955ac49da2e2107b67a"));

    tests.push_back(std::pair<const char*, const char*>("This string is precisely 56 characters long for a reason", "93d268e9bef6608ff1a6a96adbeee106"));
    tests.push_back(std::pair<const char*, const char*>("This string is exactly 64 characters long for a very good reason", "655c37c2c8451a60306d09f2971e49ff"));
    tests.push_back(std::pair<const char*, const char*>("This string is also a specific length.  It is exactly 128 characters long for a very good reason as well. We are testing bounds.", "2ac62baa5be7fa36587c55691c026b35"));

    int passed = 0;
    int passed_h = 0;
    int passed_c = 0;

    /* run our tests */
    for (unsigned int i = 0; i < tests.size(); i++) {
        bool passed_hash = 0;
        bool passed_convert = 0;

        /* calculate the sig for our test string */
        md5::md5_t md5(tests[i].first, strlen(tests[i].first), sig);

        /* convert from the sig to a string rep */
        md5::sig_to_string(sig, str, sizeof(str));
        if (strcmp(str, tests[i].second) == 0) {
            passed_hash = true;
            passed_h++;
        }

        /* convert from the string back into a MD5 signature */
        md5::sig_from_string(sig2, str);
        if (memcmp(sig, sig2, MD5_SIZE) == 0) {
            passed_convert = true;
            passed_c++;
        }

        if (passed_hash and passed_convert) {
            std::cout << "TEST " << i + 1 << " PASSED" << std::endl;
            passed++;
        } else {
            std::cout << "TEST " << i + 1 << " FAILED" << std::endl;
        }
    }

    std::cout << std::endl << "*******************************" << std::endl
              << "    " << passed << " of " << tests.size() << " tests passed" << std::endl;
    if (passed != tests.size()) {
        std::cout << std::endl << "   Please notify developer" << std::endl;
        std::cout << "  " << passed_h << " passed hashing check" << std::endl
                  << "  " << passed_h << " passed comparison check" << std::endl;
    }
    std::cout << "*******************************" << std::endl;
}

/*
 * print the usage message
 */
static void usage(void) {
    (void)fprintf(stderr, "Usage: md5_t [-r file]\n");
    exit(1);
}

int main(int argc, char **argv) {
    char do_read = 0;
    char* infile = NULL;

    argc--;
    argv++;

    /* process the args */
    for (; *argv != NULL; argc--, argv++) {
        if (**argv != '-') {
            continue;
        }

        switch (*(*argv + 1)) {
            case 'r':
                do_read = 1;
                argc--;
                argv++;

                if (argc == 0) {
                    usage();
                }

                infile = *argv;
                break;

            default:
                usage();
                break;
            }
    }

    if (argc > 0) {
        usage();
    }

    /* do we need to read in from stdin */
    if (do_read) {
        read_file(infile);
    } else {
        run_tests();
    }

    return 0;
}

<commit_msg>minor wording fix and spacing<commit_after>/*
 * A little test program for md5 code which does a md5 on all the
 * bytes sent to stdin.
 */

#include <string.h>
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <vector>

#include "../src/md5.h"

/*
 * Print a signature
 */
static void print_sig(const unsigned char *sig) {
    const unsigned char* sig_p;

    for (sig_p = sig; sig_p < sig + MD5_SIZE; sig_p++) {
        (void)printf("%02x", *sig_p);
    }
}

/*
 * Read in from stdin and run MD5 on the input
 */
static void read_file(const char* filename) {
    unsigned char sig[MD5_SIZE];
    char buffer[4096];
    md5::md5_t md5;
    bool useCin;
    std::ifstream file;

    if (filename[0] == '-') {
        useCin = true;
    } else {
        useCin = false;
        file.open(filename, std::ios::binary);
        if (!file.is_open()) {
            std::cerr << "failed to open file " << filename << std::endl;
            exit(1);
        }
    }

    /* iterate over file */
    if (useCin) {
        const char* input = filename + 1;
        std::cout << "Processing: '" << input << "'\n";
        md5.process(input, strlen(input));
    } else {
        do {
            file.read(buffer, 4096);
            md5.process(buffer, file.gcount());
        } while (file);
    }

    md5.finish(sig);

    (void)printf("%25s '", "Resulting signature:");
    print_sig(sig);
    (void)printf("'\n");

    /* convert to string to print */
    md5::sig_to_string(sig, buffer, sizeof(buffer));
    (void)printf("%25s '%s'\n", "Results of md5_to_string:", buffer);

    /* now we convert it from string back into the sig */
    md5::sig_from_string(sig, buffer);

    (void)printf("%25s '", "After md5_from_string:");
    print_sig(sig);
    (void)printf("'\n");
}

static void run_tests(void) {
    unsigned char sig[MD5_SIZE], sig2[MD5_SIZE];
    char str[MD5_STRING_SIZE];

  /* MD5 Test Suite from RFC1321 */
    std::vector<std::pair<const char*, const char*> > tests;
    tests.push_back(std::pair<const char*, const char*>("", "d41d8cd98f00b204e9800998ecf8427e"));
    tests.push_back(std::pair<const char*, const char*>("a", "0cc175b9c0f1b6a831c399e269772661"));
    tests.push_back(std::pair<const char*, const char*>("abc", "900150983cd24fb0d6963f7d28e17f72"));
    tests.push_back(std::pair<const char*, const char*>("message digest", "f96b697d7cb7938d525a2f31aaf161d0"));
    tests.push_back(std::pair<const char*, const char*>("abcdefghijklmnopqrstuvwxyz", "c3fcd3d76192e4007dfb496cca67e13b"));
    tests.push_back(std::pair<const char*, const char*>("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "d174ab98d277d9f5a5611c2c9f419d9f"));
    tests.push_back(std::pair<const char*, const char*>("12345678901234567890123456789012345678901234567890123456789012345678901234567890", "57edf4a22be3c955ac49da2e2107b67a"));

    tests.push_back(std::pair<const char*, const char*>("This string is precisely 56 characters long for a reason", "93d268e9bef6608ff1a6a96adbeee106"));
    tests.push_back(std::pair<const char*, const char*>("This string is exactly 64 characters long for a very good reason", "655c37c2c8451a60306d09f2971e49ff"));
    tests.push_back(std::pair<const char*, const char*>("This string is also a specific length.  It is exactly 128 characters long for a very good reason as well. We are testing bounds.", "2ac62baa5be7fa36587c55691c026b35"));

    int passed = 0;
    int passed_h = 0;
    int passed_c = 0;

    /* run our tests */
    for (unsigned int i = 0; i < tests.size(); i++) {
        bool passed_hash = 0;
        bool passed_convert = 0;

        /* calculate the sig for our test string */
        md5::md5_t md5(tests[i].first, strlen(tests[i].first), sig);

        /* convert from the sig to a string rep */
        md5::sig_to_string(sig, str, sizeof(str));
        if (strcmp(str, tests[i].second) == 0) {
            passed_hash = true;
            passed_h++;
        }

        /* convert from the string back into a MD5 signature */
        md5::sig_from_string(sig2, str);
        if (memcmp(sig, sig2, MD5_SIZE) == 0) {
            passed_convert = true;
            passed_c++;
        }

        if (passed_hash and passed_convert) {
            std::cout << "TEST " << i + 1 << " PASSED" << std::endl;
            passed++;
        } else {
            std::cout << "TEST " << i + 1 << " FAILED" << std::endl;
        }
    }

    std::cout << std::endl << "*******************************" << std::endl
              << "    " << passed << " of " << tests.size() << " tests passed" << std::endl;
    if (passed != tests.size()) {
        std::cout << std::endl << "   Please notify developer" << std::endl;
        std::cout << "  " << passed_h << " passed hashing check" << std::endl
                  << "  " << passed_h << " passed comparison check" << std::endl;
    }
    std::cout << "*******************************" << std::endl;
}

/*
 * print the usage message
 */
static void usage(void) {
    (void)fprintf(stderr, "Usage: md5_t [-r file]\n");
    exit(1);
}

int main(int argc, char **argv) {
    char do_read = 0;
    char* infile = NULL;

    argc--;
    argv++;

    /* process the args */
    for (; *argv != NULL; argc--, argv++) {
        if (**argv != '-') {
            continue;
        }

        switch (*(*argv + 1)) {
            case 'r':
                do_read = 1;
                argc--;
                argv++;

                if (argc == 0) {
                    usage();
                }

                infile = *argv;
                break;

            default:
                usage();
                break;
        }
    }

    if (argc > 0) {
        usage();
    }

    /* do we need to read in from stdin */
    if (do_read) {
        read_file(infile);
    } else {
        run_tests();
    }

    return 0;
}

<|endoftext|>


<commit_before>#include <list.h>
#include <unique_ptr.h>
#include <shared_ptr.h>
#include <algorithm.h>
#include <string.h>
#include "yatf/include/yatf.h"

using namespace yacppl;

TEST(mixed, can_create_shared_pointer_list) {
    list<shared_ptr<int>> list;
    auto ptr1 = make_shared<int>(5);
    list.push_front(ptr1);
    list.push_front(shared_ptr<int>(new int(6)));
    auto it = list.begin();
    REQUIRE(**it == 6);
    REQUIRE(it->get_ref_count() == 1);
    it++;
    REQUIRE(**it == 5);
    REQUIRE(it->get_ref_count() == 2);
}

TEST(mixed, can_use_for_each_on_list) {
    list<int> list;
    int result[3];
    list.push_front(3);
    list.push_front(5);
    list.push_front(78);
    int i = 0;
    for_each(list, [&](int &e) { result[i++] = e; });
    REQUIRE(result[0] == 78);
    REQUIRE(result[1] == 5);
    REQUIRE(result[2] == 3);
    REQUIRE(count(list, 78) == 1);
    for_each(list.begin(), list.end(), [](int &e) { e = 22; });
    i = 0;
    for_each(list, [&](int &e) { result[i++] = e; });
    REQUIRE(result[0] == 22);
    REQUIRE(result[1] == 22);
    REQUIRE(result[2] == 22);
}

TEST(mixed, can_use_count_on_list) {
    list<int> list{3, 7, 8, 6, 5, 3, 7, 9, 60, 55, 8, 6};
    REQUIRE(count(list, 3) == 2);
    REQUIRE(count(list, 9) == 1);
    REQUIRE(count(list, 20) == 0);
    auto result1 = count_if(list, [](const int &e) { return e > 3; });
    REQUIRE(result1 == 10);
    auto result2 = count_if(list, [](const int &e) { return e < 3; });
    REQUIRE(result2 == 0);
    auto result3 = count_if(list, [](const int &e) {
        (void) e;
        return 1;
    });
    REQUIRE(result3 == 12);
    auto result4 = count_if(list, [](const int &e) {
        (void) e;
        return 0;
    });
    REQUIRE(result4 == 0);
}

TEST(mixed, can_swap_same_size_lists) {
    list<int> list1{3, 7, 8, 6};
    list<int> list2{9, 15, -3, 21};
    swap(list1, list2);
    REQUIRE(list1.size() ==  4);
    REQUIRE(list1.front() == 9);
    REQUIRE(list1.back() == 21);
    REQUIRE(list2.size() == 4);
    REQUIRE(list2.front() == 3);
    REQUIRE(list2.back() == 6);
    swap(list1, list2);
    REQUIRE(list2.size() == 4);
    REQUIRE(list2.front() == 9);
    REQUIRE(list2.back() == 21);
    REQUIRE(list1.size() == 4);
    REQUIRE(list1.front() == 3);
    REQUIRE(list1.back() == 6);
}

TEST(mixed, can_swap_different_size_lists) {
    list<int> list1{3, 7, 8, 6, 8, 4};
    list<int> list2{9, 15, -3, 21};
    swap(list1, list2);
    REQUIRE(list1.size() == 4);
    REQUIRE(list1.front() == 9);
    REQUIRE(list1.back() == 21);
    REQUIRE(list2.size() == 6);
    REQUIRE(list2.front() == 3);
    REQUIRE(list2.back() == 4);
    swap(list1, list2);
    REQUIRE(list2.size() == 4);
    REQUIRE(list2.front() == 9);
    REQUIRE(list2.back() == 21);
    REQUIRE(list1.size() == 6);
    REQUIRE(list1.front() == 3);
    REQUIRE(list1.back() == 4);
}

TEST(mixed, can_fill_list) {
    list<int> list;
    list.resize(30);
    fill(list, 945);
    REQUIRE(list.size() == 30);
    REQUIRE(list.front() == 945);
    REQUIRE(list.back() == 945);
    list.resize(10);
    fill(list, 3);
    REQUIRE(list.size() == 10);
    REQUIRE(list.front() == 3);
    REQUIRE(list.back() == 3);
}

<commit_msg>Update mixed tests<commit_after>#include <list.h>
#include <unique_ptr.h>
#include <shared_ptr.h>
#include <algorithm.h>
#include <string.h>
#include "yatf/include/yatf.h"

using namespace yacppl;

TEST(mixed, can_create_shared_pointer_list) {
    list<shared_ptr<int>> list;
    auto ptr1 = make_shared<int>(5);
    list.push_front(ptr1);
    list.push_front(shared_ptr<int>(new int(6)));
    auto it = list.begin();
    REQUIRE_EQ(**it, 6);
    REQUIRE(it->get_ref_count() == 1);
    it++;
    REQUIRE_EQ(**it, 5);
    REQUIRE(it->get_ref_count() == 2);
}

TEST(mixed, can_use_for_each_on_list) {
    list<int> list;
    int result[3];
    list.push_front(3);
    list.push_front(5);
    list.push_front(78);
    int i = 0;
    for_each(list, [&](int &e) { result[i++] = e; });
    REQUIRE_EQ(result[0], 78);
    REQUIRE_EQ(result[1], 5);
    REQUIRE_EQ(result[2], 3);
    REQUIRE_EQ(count(list, 78), 1);
    for_each(list.begin(), list.end(), [](int &e) { e = 22; });
    i = 0;
    for_each(list, [&](int &e) { result[i++] = e; });
    REQUIRE_EQ(result[0], 22);
    REQUIRE_EQ(result[1], 22);
    REQUIRE_EQ(result[2], 22);
}

TEST(mixed, can_use_count_on_list) {
    list<int> list{3, 7, 8, 6, 5, 3, 7, 9, 60, 55, 8, 6};
    REQUIRE_EQ(count(list, 3), 2);
    REQUIRE_EQ(count(list, 9), 1);
    REQUIRE_EQ(count(list, 20), 0);
    auto result1 = count_if(list, [](const int &e) { return e > 3; });
    REQUIRE_EQ(result1, 10);
    auto result2 = count_if(list, [](const int &e) { return e < 3; });
    REQUIRE_EQ(result2, 0);
    auto result3 = count_if(list, [](const int &e) {
        (void) e;
        return 1;
    });
    REQUIRE_EQ(result3, 12);
    auto result4 = count_if(list, [](const int &e) {
        (void) e;
        return 0;
    });
    REQUIRE_EQ(result4, 0);
}

TEST(mixed, can_swap_same_size_lists) {
    list<int> list1{3, 7, 8, 6};
    list<int> list2{9, 15, -3, 21};
    swap(list1, list2);
    REQUIRE(list1.size() ==  4);
    REQUIRE_EQ(list1.front(), 9);
    REQUIRE_EQ(list1.back(), 21);
    REQUIRE(list2.size() == 4);
    REQUIRE_EQ(list2.front(), 3);
    REQUIRE_EQ(list2.back(), 6);
    swap(list1, list2);
    REQUIRE(list2.size() == 4);
    REQUIRE_EQ(list2.front(), 9);
    REQUIRE_EQ(list2.back(), 21);
    REQUIRE(list1.size() == 4);
    REQUIRE_EQ(list1.front(), 3);
    REQUIRE_EQ(list1.back(), 6);
}

TEST(mixed, can_swap_different_size_lists) {
    list<int> list1{3, 7, 8, 6, 8, 4};
    list<int> list2{9, 15, -3, 21};
    swap(list1, list2);
    REQUIRE(list1.size() == 4);
    REQUIRE_EQ(list1.front(), 9);
    REQUIRE_EQ(list1.back(), 21);
    REQUIRE(list2.size() == 6);
    REQUIRE_EQ(list2.front(), 3);
    REQUIRE_EQ(list2.back(), 4);
    swap(list1, list2);
    REQUIRE(list2.size() == 4);
    REQUIRE_EQ(list2.front(), 9);
    REQUIRE_EQ(list2.back(), 21);
    REQUIRE(list1.size() == 6);
    REQUIRE_EQ(list1.front(), 3);
    REQUIRE_EQ(list1.back(), 4);
}

TEST(mixed, can_fill_list) {
    list<int> list;
    list.resize(30);
    fill(list, 945);
    REQUIRE(list.size() == 30);
    REQUIRE_EQ(list.front(), 945);
    REQUIRE_EQ(list.back(), 945);
    list.resize(10);
    fill(list, 3);
    REQUIRE(list.size() == 10);
    REQUIRE_EQ(list.front(), 3);
    REQUIRE_EQ(list.back(), 3);
}

<|endoftext|>


<commit_before>/*  This file is part of the Vc library.

    Copyright (C) 2009 Matthias Kretz <kretz@kde.org>

    Vc is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as
    published by the Free Software Foundation, either version 3 of
    the License, or (at your option) any later version.

    Vc is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with Vc.  If not, see <http://www.gnu.org/licenses/>.

*/

#include <Vc/Vc>
#include "unittest.h"
#include <iostream>
#include <cstring>

using namespace Vc;

template<typename Vec> void alignedStore()
{
    typedef typename Vec::EntryType T;
    enum {
        Count = 256 * 1024 / sizeof(T)
    };

    Memory<Vec, Count> array;
    // do the memset to make sure the array doesn't have the old data from a previous call which
    // would mask a real problem
    std::memset(array, 0xff, Count * sizeof(T));
    T xValue = 1;
    const Vec x(xValue);
    for (int i = 0; i < Count; i += Vec::Size) {
        x.store(&array[i]);
    }

    for (int i = 0; i < Count; ++i) {
        COMPARE(array[i], xValue);
    }
}

template<typename Vec> void unalignedStore()
{
    typedef typename Vec::EntryType T;
    enum {
        Count = 256 * 1024 / sizeof(T)
    };

    Memory<Vec, Count> array;
    // do the memset to make sure the array doesn't have the old data from a previous call which
    // would mask a real problem
    std::memset(array, 0xff, Count * sizeof(T));
    T xValue = 1;
    const Vec x(xValue);
    for (int i = 1; i < Count - Vec::Size + 1; i += Vec::Size) {
        x.store(&array[i], Unaligned);
    }

    for (int i = 1; i < Count - Vec::Size + 1; ++i) {
        COMPARE(array[i], xValue);
    }
}

template<typename Vec> void streamingAndAlignedStore()
{
    typedef typename Vec::EntryType T;
    enum {
        Count = 256 * 1024 / sizeof(T)
    };

    Memory<Vec, Count> array;
    // do the memset to make sure the array doesn't have the old data from a previous call which
    // would mask a real problem
    std::memset(array, 0xff, Count * sizeof(T));
    T xValue = 1;
    const Vec x(xValue);
    for (int i = 0; i < Count; i += Vec::Size) {
        x.store(&array[i], Streaming | Aligned);
    }

    for (int i = 0; i < Count; ++i) {
        COMPARE(array[i], xValue);
    }
}

template<typename Vec> void streamingAndUnalignedStore()
{
    typedef typename Vec::EntryType T;
    enum {
        Count = 256 * 1024 / sizeof(T)
    };

    Memory<Vec, Count> array;
    // do the memset to make sure the array doesn't have the old data from a previous call which
    // would mask a real problem
    std::memset(array, 0xff, Count * sizeof(T));
    T xValue = 1;
    const Vec x(xValue);
    for (int i = 1; i < Count - Vec::Size + 1; i += Vec::Size) {
        x.store(&array[i], Streaming | Unaligned);
    }

    for (int i = 1; i < Count - Vec::Size + 1; ++i) {
        COMPARE(array[i], xValue);
    }
}

template<typename Vec> void maskedStore()
{
    typedef typename Vec::EntryType T;
    typedef typename Vec::Mask M;
    M mask;
    {
        typedef typename Vec::IndexType I;
        const I tmp(IndexesFromZero);
        const typename I::Mask k = (tmp & I(One)) > 0;
        mask = M(k);
    }

    const int count = 256 * 1024 / sizeof(T);
    const int outerCount = count / Vec::Size;
    typename Vec::Memory array[outerCount];
    T nullValue = 0;
    std::memset(array, 0, count * sizeof(T));
    T setValue = 170;
    const Vec x(setValue);
    for (int i = 0; i < outerCount; ++i) {
        x.store(array[i], mask);
    }

    for (int i = 1; i < count; i += 2) {
        COMPARE(array[i / Vec::Size][i % Vec::Size], setValue);
    }
    for (int i = 0; i < count; i += 2) {
        COMPARE(array[i / Vec::Size][i % Vec::Size], nullValue);
    }
}

int main(int argc, char **argv)
{
    initTest(argc, argv);

    testAllTypes(alignedStore);
    testAllTypes(unalignedStore);
    testAllTypes(streamingAndAlignedStore);
    testAllTypes(streamingAndUnalignedStore);

    if (float_v::Size > 1) {
        runTest(maskedStore<int_v>);
        runTest(maskedStore<uint_v>);
        runTest(maskedStore<float_v>);
        runTest(maskedStore<double_v>);
        runTest(maskedStore<short_v>);
        runTest(maskedStore<ushort_v>);
        runTest(maskedStore<sfloat_v>);
    }
    return 0;
}
<commit_msg>more info on failure in store unit test<commit_after>/*  This file is part of the Vc library.

    Copyright (C) 2009 Matthias Kretz <kretz@kde.org>

    Vc is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as
    published by the Free Software Foundation, either version 3 of
    the License, or (at your option) any later version.

    Vc is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with Vc.  If not, see <http://www.gnu.org/licenses/>.

*/

#include <Vc/Vc>
#include "unittest.h"
#include <iostream>
#include <cstring>

using namespace Vc;

template<typename Vec> void alignedStore()
{
    typedef typename Vec::EntryType T;
    enum {
        Count = 256 * 1024 / sizeof(T)
    };

    Memory<Vec, Count> array;
    // do the memset to make sure the array doesn't have the old data from a previous call which
    // would mask a real problem
    std::memset(array, 0xff, Count * sizeof(T));
    T xValue = 1;
    const Vec x(xValue);
    for (int i = 0; i < Count; i += Vec::Size) {
        x.store(&array[i]);
    }

    for (int i = 0; i < Count; ++i) {
        COMPARE(array[i], xValue);
    }
}

template<typename Vec> void unalignedStore()
{
    typedef typename Vec::EntryType T;
    enum {
        Count = 256 * 1024 / sizeof(T)
    };

    Memory<Vec, Count> array;
    // do the memset to make sure the array doesn't have the old data from a previous call which
    // would mask a real problem
    std::memset(array, 0xff, Count * sizeof(T));
    T xValue = 1;
    const Vec x(xValue);
    for (int i = 1; i < Count - Vec::Size + 1; i += Vec::Size) {
        x.store(&array[i], Unaligned);
    }

    for (int i = 1; i < Count - Vec::Size + 1; ++i) {
        COMPARE(array[i], xValue);
    }
}

template<typename Vec> void streamingAndAlignedStore()
{
    typedef typename Vec::EntryType T;
    enum {
        Count = 256 * 1024 / sizeof(T)
    };

    Memory<Vec, Count> array;
    // do the memset to make sure the array doesn't have the old data from a previous call which
    // would mask a real problem
    std::memset(array, 0xff, Count * sizeof(T));
    T xValue = 1;
    const Vec x(xValue);
    for (int i = 0; i < Count; i += Vec::Size) {
        x.store(&array[i], Streaming | Aligned);
    }

    for (int i = 0; i < Count; ++i) {
        COMPARE(array[i], xValue);
    }
}

template<typename Vec> void streamingAndUnalignedStore()
{
    typedef typename Vec::EntryType T;
    enum {
        Count = 256 * 1024 / sizeof(T)
    };

    Memory<Vec, Count> array;
    // do the memset to make sure the array doesn't have the old data from a previous call which
    // would mask a real problem
    std::memset(array, 0xff, Count * sizeof(T));
    T xValue = 1;
    const Vec x(xValue);
    for (int i = 1; i < Count - Vec::Size + 1; i += Vec::Size) {
        x.store(&array[i], Streaming | Unaligned);
    }

    for (int i = 1; i < Count - Vec::Size + 1; ++i) {
        COMPARE(array[i], xValue);
    }
}

template<typename Vec> void maskedStore()
{
    typedef typename Vec::EntryType T;
    typedef typename Vec::Mask M;
    M mask;
    {
        typedef typename Vec::IndexType I;
        const I tmp(IndexesFromZero);
        const typename I::Mask k = (tmp & I(One)) > 0;
        mask = M(k);
    }

    const int count = 256 * 1024 / sizeof(T);
    const int outerCount = count / Vec::Size;
    typename Vec::Memory array[outerCount];
    T nullValue = 0;
    std::memset(array, 0, count * sizeof(T));
    T setValue = 170;
    const Vec x(setValue);
    for (int i = 0; i < outerCount; ++i) {
        x.store(array[i], mask);
    }

    for (int i = 1; i < count; i += 2) {
        COMPARE(array[i / Vec::Size][i % Vec::Size], setValue) << ", i: " << i << ", count: " << count << ", outer: " << outerCount;
    }
    for (int i = 0; i < count; i += 2) {
        COMPARE(array[i / Vec::Size][i % Vec::Size], nullValue) << ", i: " << i << ", count: " << count << ", outer: " << outerCount;
    }
}

int main(int argc, char **argv)
{
    initTest(argc, argv);

    testAllTypes(alignedStore);
    testAllTypes(unalignedStore);
    testAllTypes(streamingAndAlignedStore);
    testAllTypes(streamingAndUnalignedStore);

    if (float_v::Size > 1) {
        runTest(maskedStore<int_v>);
        runTest(maskedStore<uint_v>);
        runTest(maskedStore<float_v>);
        runTest(maskedStore<double_v>);
        runTest(maskedStore<short_v>);
        runTest(maskedStore<ushort_v>);
        runTest(maskedStore<sfloat_v>);
    }
    return 0;
}
<|endoftext|>


<commit_before>#include <string>
#include "Mutex.h"
#include "ThreadCreator.h"
#include "UniSetTypes.h"

using namespace std;
using namespace UniSetTypes;

uniset_mutex m;

class MyClass
{
	public:
		MyClass( const std::string name ): nm(name)
		{
			thr = new ThreadCreator<MyClass>(this, &MyClass::thread);
		}

		~MyClass()
		{
			delete thr;
		}

		void execute()
		{
			thr->start();
		}

	protected:
		std::string nm;

		void thread()
		{
			while(1)
			{
				{
					cerr << nm << ": before release=" << m.isRelease() << endl;
					uniset_mutex_lock l(m,5000);
					cerr << nm << ": after release=" << m.isRelease() << endl;
				}
				msleep(300);
			}
		}

		private:
			ThreadCreator<MyClass>* thr;
	};

int main( int argc, const char **argv )
{
	MyClass* mc1 = new MyClass("t1");
	MyClass* mc2 = new MyClass("t2");

//	m.lock();
	mc1->execute();
	msleep(200);
	mc2->execute();
	pause();
//	m.unlock();
	return 0;
}
<commit_msg>test correct<commit_after>#include <string>
#include <sstream>
#include "Mutex.h"
#include "ThreadCreator.h"
#include "UniSetTypes.h"

using namespace std;
using namespace UniSetTypes;

uniset_mutex m;

class MyClass
{
	public:
		MyClass( const std::string name ): nm(name)
		{
			thr = new ThreadCreator<MyClass>(this, &MyClass::thread);
		}

		~MyClass()
		{
			delete thr;
		}

		void execute()
		{
			thr->start();
		}

	protected:
		std::string nm;

		void thread()
		{
			while(1)
			{
				{
					cerr << nm << ": before release=" << m.isRelease() << endl;
					uniset_mutex_lock l(m);
					msleep(30);
					cerr << nm << ": after release=" << m.isRelease() << endl;
				}
				msleep(10);
			}
		}

		private:
			ThreadCreator<MyClass>* thr;
	};

int main( int argc, const char **argv )
{
	int max = 10;

	if( argc > 1 )
		max = UniSetTypes::uni_atoi(argv[1]);

	for( int i=0; i<max; i++ )
	{
		ostringstream s;
		s << "t" << i;
     	MyClass* t = new MyClass(s.str());
     	t->execute();
     	msleep(50);
	}

	pause();
	return 0;
}
<|endoftext|>


<commit_before>/*
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * InterfacePicker.cpp
 * Chooses an interface to listen on
 * Copyright (C) 2005-2010 Simon Newton
 */

#if HAVE_CONFIG_H
#  include <config.h>
#endif

#ifdef HAVE_GETIFADDRS
  #ifdef HAVE_LINUX_IF_PACKET_H
    #define OLA_USE_GETIFADDRS
  #endif
#endif

#ifdef OLA_USE_GETIFADDRS
  #include <ifaddrs.h>
  #include <linux/types.h>
  #include <linux/if_packet.h>
#endif

#include <arpa/inet.h>
#include <errno.h>
#include <net/if.h>
#ifdef HAVE_SOCKADDR_DL_STRUCT
#include <net/if_dl.h>
#endif
#include <string.h>
#include <sys/ioctl.h>
#include <algorithm>
#include <string>
#include <vector>

#include "common/network/PosixInterfacePicker.h"
#include "ola/Logging.h"
#include "ola/network/NetworkUtils.h"

namespace ola {
namespace network {

using std::string;
using std::vector;

/*
 * Return a vector of interfaces on the system.
 */
vector<Interface> PosixInterfacePicker::GetInterfaces() const {
  vector<Interface> interfaces;
  string last_dl_iface_name;
  uint8_t hwlen = 0;
  char *hwaddr = NULL;

  // create socket to get iface config
  int sd = socket(PF_INET, SOCK_DGRAM, 0);

  if (sd < 0) {
    OLA_WARN << "Could not create socket " << strerror(errno);
    return interfaces;
  }

  // use ioctl to get a listing of interfaces
  char *buffer;  // holds the iface data
  unsigned int lastlen = 0;  // the amount of data returned by the last ioctl
  unsigned int len = INITIAL_IFACE_COUNT;

  while (true) {
    struct ifconf ifc;
    ifc.ifc_len = len * sizeof(struct ifreq);
    buffer = new char[ifc.ifc_len];
    ifc.ifc_buf = buffer;

    if (ioctl(sd, SIOCGIFCONF, &ifc) < 0) {
      if (errno != EINVAL || lastlen != 0) {
        OLA_WARN << "ioctl error " << strerror(errno);
        delete[] buffer;
        return interfaces;
      }
    } else {
      if (static_cast<unsigned int>(ifc.ifc_len) == lastlen) {
        lastlen = ifc.ifc_len;
        break;
      }
      lastlen = ifc.ifc_len;
    }
    len += IFACE_COUNT_INC;
    delete[] buffer;
  }

  // loop through each iface
  for (char *ptr = buffer; ptr < buffer + lastlen;) {
    struct ifreq *iface = (struct ifreq*) ptr;
    ptr += GetIfReqSize(ptr);

#ifdef HAVE_SOCKADDR_DL_STRUCT
    if (iface->ifr_addr.sa_family == AF_LINK) {
      struct sockaddr_dl *sdl = (struct sockaddr_dl*) &iface->ifr_addr;
      last_dl_iface_name.assign(sdl->sdl_data, sdl->sdl_nlen);
      hwaddr = sdl->sdl_data + sdl->sdl_nlen;
      hwlen = sdl->sdl_alen;
    }
#endif

    // look for AF_INET interfaces only
    if (iface->ifr_addr.sa_family != AF_INET) {
      OLA_DEBUG << "skipping " << iface->ifr_name <<
        " because it's not af_inet";
      continue;
    }

    struct ifreq ifrcopy = *iface;
    if (ioctl(sd, SIOCGIFFLAGS, &ifrcopy) < 0) {
      OLA_WARN << "ioctl error for " << iface->ifr_name << ":"
        << strerror(errno);
      continue;
    }

    if (!(ifrcopy.ifr_flags & IFF_UP)) {
      OLA_DEBUG << "skipping " << iface->ifr_name << " because it's down";
      continue;
    }

    if (ifrcopy.ifr_flags & IFF_LOOPBACK) {
      OLA_DEBUG << "skipping " << iface->ifr_name <<
        " because it's a loopback";
      continue;
    }

    Interface interface;
    interface.name = iface->ifr_name;
    if (interface.name == last_dl_iface_name && hwaddr) {
      memcpy(interface.hw_address, hwaddr,
             std::min(hwlen, (uint8_t) MAC_LENGTH));
    }
    struct sockaddr_in *sin = (struct sockaddr_in *) &iface->ifr_addr;
    interface.ip_address = sin->sin_addr;

    // fetch bcast address
#ifdef SIOCGIFBRDADDR
    if (ifrcopy.ifr_flags & IFF_BROADCAST) {
      if (ioctl(sd, SIOCGIFBRDADDR, &ifrcopy) < 0) {
        OLA_WARN << "ioctl error " << strerror(errno);
      } else {
        sin = (struct sockaddr_in *) &ifrcopy.ifr_broadaddr;
        interface.bcast_address = sin->sin_addr;
      }
    }
#endif

    // fetch subnet address
#ifdef  SIOCGIFNETMASK
    if (ioctl(sd, SIOCGIFNETMASK, &ifrcopy) < 0) {
      OLA_WARN << "ioctl error " << strerror(errno);
    } else {
      sin = (struct sockaddr_in *) &ifrcopy.ifr_broadaddr;
      interface.subnet_address = sin->sin_addr;
    }
#endif

    // fetch hardware address
#ifdef SIOCGIFHWADDR
    if (ifrcopy.ifr_flags & SIOCGIFHWADDR) {
      if (ioctl(sd, SIOCGIFHWADDR, &ifrcopy) < 0) {
        OLA_WARN << "ioctl error" << strerror(errno);
      } else {
        memcpy(interface.hw_address, ifrcopy.ifr_hwaddr.sa_data, MAC_LENGTH);
      }
    }
#endif

    /* ok, if that all failed we should prob try and use sysctl to work out the bcast
     * and hware addresses
     * i'll leave that for another day
     */
    interfaces.push_back(interface);
  }
  close(sd);
  delete[] buffer;
  return interfaces;
}

/*
 * Return the size of an ifreq structure in a cross platform manner.
 * @param data a pointer to an ifreq structure
 * @return the size of the ifreq structure
 */
unsigned int PosixInterfacePicker::GetIfReqSize(const char *data) const {
  const struct ifreq *iface = (struct ifreq*) data;

#ifdef HAVE_SOCKADDR_SA_LEN
  unsigned int socket_len = iface->ifr_addr.sa_len;
#else
  unsigned int socket_len = sizeof(struct sockaddr);
  switch (iface->ifr_addr.sa_family) {
    case AF_INET:
      socket_len = sizeof(struct sockaddr_in);
      break;
#ifdef IPV6
    case AF_INET6:
      socket_len = sizeof(struct sockaddr_in6);
      break;
#endif
#ifdef HAVE_SOCKADDR_DL_STRUCT
    case AF_LINK:
      socket_len = sizeof(struct sockaddr_dl);
      break;
#endif
  }
#endif

  // We can't assume sizeof(ifreq) = IFNAMSIZ + sizeof(sockaddr), this isn't
  // the case on some 64bit linux systems.
  if (socket_len > sizeof(struct ifreq) - IFNAMSIZ)
    return IFNAMSIZ + socket_len;
  else
    return sizeof(struct ifreq);
}
}  // network
}  // ola
<commit_msg> * add some more debugging to the interface picker<commit_after>/*
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * InterfacePicker.cpp
 * Chooses an interface to listen on
 * Copyright (C) 2005-2010 Simon Newton
 */

#if HAVE_CONFIG_H
#  include <config.h>
#endif

#ifdef HAVE_GETIFADDRS
  #ifdef HAVE_LINUX_IF_PACKET_H
    #define OLA_USE_GETIFADDRS
  #endif
#endif

#ifdef OLA_USE_GETIFADDRS
  #include <ifaddrs.h>
  #include <linux/types.h>
  #include <linux/if_packet.h>
#endif

#include <arpa/inet.h>
#include <errno.h>
#include <net/if.h>
#ifdef HAVE_SOCKADDR_DL_STRUCT
#include <net/if_dl.h>
#endif
#include <string.h>
#include <sys/ioctl.h>
#include <algorithm>
#include <string>
#include <vector>

#include "common/network/PosixInterfacePicker.h"
#include "ola/Logging.h"
#include "ola/network/NetworkUtils.h"

namespace ola {
namespace network {

using std::string;
using std::vector;

/*
 * Return a vector of interfaces on the system.
 */
vector<Interface> PosixInterfacePicker::GetInterfaces() const {
  vector<Interface> interfaces;
  string last_dl_iface_name;
  uint8_t hwlen = 0;
  char *hwaddr = NULL;

  // create socket to get iface config
  int sd = socket(PF_INET, SOCK_DGRAM, 0);

  if (sd < 0) {
    OLA_WARN << "Could not create socket " << strerror(errno);
    return interfaces;
  }

  // use ioctl to get a listing of interfaces
  char *buffer;  // holds the iface data
  unsigned int lastlen = 0;  // the amount of data returned by the last ioctl
  unsigned int len = INITIAL_IFACE_COUNT;

  while (true) {
    struct ifconf ifc;
    ifc.ifc_len = len * sizeof(struct ifreq);
    buffer = new char[ifc.ifc_len];
    ifc.ifc_buf = buffer;

    if (ioctl(sd, SIOCGIFCONF, &ifc) < 0) {
      if (errno != EINVAL || lastlen != 0) {
        OLA_WARN << "ioctl error " << strerror(errno);
        delete[] buffer;
        return interfaces;
      }
    } else {
      if (static_cast<unsigned int>(ifc.ifc_len) == lastlen) {
        lastlen = ifc.ifc_len;
        break;
      }
      lastlen = ifc.ifc_len;
    }
    len += IFACE_COUNT_INC;
    delete[] buffer;
  }

  // loop through each iface
  for (char *ptr = buffer; ptr < buffer + lastlen;) {
    struct ifreq *iface = (struct ifreq*) ptr;
    ptr += GetIfReqSize(ptr);

#ifdef HAVE_SOCKADDR_DL_STRUCT
    if (iface->ifr_addr.sa_family == AF_LINK) {
      struct sockaddr_dl *sdl = (struct sockaddr_dl*) &iface->ifr_addr;
      last_dl_iface_name.assign(sdl->sdl_data, sdl->sdl_nlen);
      hwaddr = sdl->sdl_data + sdl->sdl_nlen;
      hwlen = sdl->sdl_alen;
    }
#endif

    // look for AF_INET interfaces only
    if (iface->ifr_addr.sa_family != AF_INET) {
      OLA_DEBUG << "skipping " << iface->ifr_name <<
        " because it's not af_inet";
      continue;
    }

    struct ifreq ifrcopy = *iface;
    if (ioctl(sd, SIOCGIFFLAGS, &ifrcopy) < 0) {
      OLA_WARN << "ioctl error for " << iface->ifr_name << ":"
        << strerror(errno);
      continue;
    }

    if (!(ifrcopy.ifr_flags & IFF_UP)) {
      OLA_DEBUG << "skipping " << iface->ifr_name << " because it's down";
      continue;
    }

    if (ifrcopy.ifr_flags & IFF_LOOPBACK) {
      OLA_DEBUG << "skipping " << iface->ifr_name <<
        " because it's a loopback";
      continue;
    }

    Interface interface;
    interface.name = iface->ifr_name;
    if (interface.name == last_dl_iface_name && hwaddr) {
      memcpy(interface.hw_address, hwaddr,
             std::min(hwlen, (uint8_t) MAC_LENGTH));
    }
    struct sockaddr_in *sin = (struct sockaddr_in *) &iface->ifr_addr;
    interface.ip_address = sin->sin_addr;

    // fetch bcast address
#ifdef SIOCGIFBRDADDR
    if (ifrcopy.ifr_flags & IFF_BROADCAST) {
      if (ioctl(sd, SIOCGIFBRDADDR, &ifrcopy) < 0) {
        OLA_WARN << "ioctl error " << strerror(errno);
      } else {
        sin = (struct sockaddr_in *) &ifrcopy.ifr_broadaddr;
        interface.bcast_address = sin->sin_addr;
      }
    }
#endif

    // fetch subnet address
#ifdef  SIOCGIFNETMASK
    if (ioctl(sd, SIOCGIFNETMASK, &ifrcopy) < 0) {
      OLA_WARN << "ioctl error " << strerror(errno);
    } else {
      sin = (struct sockaddr_in *) &ifrcopy.ifr_broadaddr;
      interface.subnet_address = sin->sin_addr;
    }
#endif

    // fetch hardware address
#ifdef SIOCGIFHWADDR
    if (ifrcopy.ifr_flags & SIOCGIFHWADDR) {
      if (ioctl(sd, SIOCGIFHWADDR, &ifrcopy) < 0) {
        OLA_WARN << "ioctl error" << strerror(errno);
      } else {
        memcpy(interface.hw_address, ifrcopy.ifr_hwaddr.sa_data, MAC_LENGTH);
      }
    }
#endif

    /* ok, if that all failed we should prob try and use sysctl to work out the bcast
     * and hware addresses
     * i'll leave that for another day
     */
    OLA_DEBUG << "Found: " << interface.name << ", " <<
      AddressToString(interface.ip_address) << ", " <<
      HardwareAddressToString(interface.hw_address);
    interfaces.push_back(interface);
  }
  close(sd);
  delete[] buffer;
  return interfaces;
}

/*
 * Return the size of an ifreq structure in a cross platform manner.
 * @param data a pointer to an ifreq structure
 * @return the size of the ifreq structure
 */
unsigned int PosixInterfacePicker::GetIfReqSize(const char *data) const {
  const struct ifreq *iface = (struct ifreq*) data;

#ifdef HAVE_SOCKADDR_SA_LEN
  unsigned int socket_len = iface->ifr_addr.sa_len;
#else
  unsigned int socket_len = sizeof(struct sockaddr);
  switch (iface->ifr_addr.sa_family) {
    case AF_INET:
      socket_len = sizeof(struct sockaddr_in);
      break;
#ifdef IPV6
    case AF_INET6:
      socket_len = sizeof(struct sockaddr_in6);
      break;
#endif
#ifdef HAVE_SOCKADDR_DL_STRUCT
    case AF_LINK:
      socket_len = sizeof(struct sockaddr_dl);
      break;
#endif
  }
#endif

  // We can't assume sizeof(ifreq) = IFNAMSIZ + sizeof(sockaddr), this isn't
  // the case on some 64bit linux systems.
  if (socket_len > sizeof(struct ifreq) - IFNAMSIZ)
    return IFNAMSIZ + socket_len;
  else
    return sizeof(struct ifreq);
}
}  // network
}  // ola
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: stl_types.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: pl $ $Date: 2001-05-10 12:21:01 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRUNTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRUNTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc..
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _COMPHELPER_STLTYPES_HXX_
#define _COMPHELPER_STLTYPES_HXX_

#if !defined(__SGI_STL_VECTOR_H) || !defined(__SGI_STL_MAP_H) || !defined(__SGI_STL_MULTIMAP_H)

#include <vector>
#include <map>
#include <hash_map>
#include <stack>
#include <set>
#include <math.h> // prevent conflict between exception and std::exception

using namespace std;

#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif

//... namespace comphelper ................................................
namespace comphelper
{
//.........................................................................

//========================================================================
// comparisation functions

//------------------------------------------------------------------------
struct UStringLess : public binary_function< ::rtl::OUString, ::rtl::OUString, bool>
{
    bool operator() (const ::rtl::OUString& x, const ::rtl::OUString& y) const { return x < y ? true : false;}      // construct prevents a MSVC6 warning
};
//------------------------------------------------------------------------
struct UStringMixLess : public binary_function< ::rtl::OUString, ::rtl::OUString, bool>
{
    bool m_bCaseSensitive;
public:
    UStringMixLess(bool bCaseSensitive = true):m_bCaseSensitive(bCaseSensitive){}
    bool operator() (const ::rtl::OUString& x, const ::rtl::OUString& y) const
    {
        if (m_bCaseSensitive)
            return rtl_ustr_compare(x.getStr(), y.getStr()) < 0 ? true : false;
        else
            return rtl_ustr_compareIgnoreAsciiCase(x.getStr(), y.getStr()) < 0 ? true : false;
    }

    bool isCaseSensitive() const {return m_bCaseSensitive;}
};
//------------------------------------------------------------------------
struct UStringEqual
{
    sal_Bool operator() (const ::rtl::OUString& lhs, const ::rtl::OUString& rhs) const { return lhs.equals( rhs );}
};

//------------------------------------------------------------------------
struct UStringIEqual
{
    sal_Bool operator() (const ::rtl::OUString& lhs, const ::rtl::OUString& rhs) const { return lhs.equalsIgnoreAsciiCase( rhs );}
};

//------------------------------------------------------------------------
struct UStringHash
{
    size_t operator() (const ::rtl::OUString& rStr) const {return rStr.hashCode();}
};

//------------------------------------------------------------------------
class UStringMixEqual
{
    sal_Bool m_bCaseSensitive;

public:
    UStringMixEqual(sal_Bool bCaseSensitive = sal_True):m_bCaseSensitive(bCaseSensitive){}
    sal_Bool operator() (const ::rtl::OUString& lhs, const ::rtl::OUString& rhs) const
    {
        return m_bCaseSensitive ? lhs.equals( rhs ) : lhs.equalsIgnoreAsciiCase( rhs );
    }
    sal_Bool isCaseSensitive() const {return m_bCaseSensitive;}
};

//------------------------------------------------------------------------
class UStringMixHash
{
    sal_Bool m_bCaseSensitive;

public:
    UStringMixHash(sal_Bool bCaseSensitive = sal_True):m_bCaseSensitive(bCaseSensitive){}
    size_t operator() (const ::rtl::OUString& rStr) const
    {
        return m_bCaseSensitive ? rStr.hashCode() : rStr.toAsciiUpperCase().hashCode();
    }
    sal_Bool isCaseSensitive() const {return m_bCaseSensitive;}
};

//.........................................................................
}
//... namespace comphelper ................................................

//==================================================================
// consistently defining stl-types
//==================================================================

#define DECLARE_STL_ITERATORS(classname)                            \
    typedef classname::iterator         classname##Iterator;        \
    typedef classname::const_iterator   Const##classname##Iterator  \

#define DECLARE_STL_MAP(keytype, valuetype, comparefct, classname)  \
    typedef std::map< keytype, valuetype, comparefct >  classname;  \
    DECLARE_STL_ITERATORS(classname)                                \

#define DECLARE_STL_STDKEY_MAP(keytype, valuetype, classname)               \
    DECLARE_STL_MAP(keytype, valuetype, std::less< keytype >, classname)    \

#define DECLARE_STL_VECTOR(valuetyp, classname)     \
    typedef std::vector< valuetyp >     classname;  \
    DECLARE_STL_ITERATORS(classname)                \

#define DECLARE_STL_USTRINGACCESS_MAP(valuetype, classname)                 \
    DECLARE_STL_MAP(::rtl::OUString, valuetype, ::comphelper::UStringLess, classname)   \

#define DECLARE_STL_STDKEY_SET(valuetype, classname)    \
    typedef ::std::set< valuetype > classname;          \
    DECLARE_STL_ITERATORS(classname)                    \

#define DECLARE_STL_SET(valuetype, comparefct, classname)               \
    typedef ::std::set< valuetype, comparefct > classname;  \
    DECLARE_STL_ITERATORS(classname)                        \

#endif

#endif  // _COMPHELPER_STLTYPES_HXX_

<commit_msg>#86996# +OInterfaceCompare<commit_after>/*************************************************************************
 *
 *  $RCSfile: stl_types.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: fs $ $Date: 2001-05-25 10:48:01 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRUNTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRUNTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc..
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _COMPHELPER_STLTYPES_HXX_
#define _COMPHELPER_STLTYPES_HXX_

#if !defined(__SGI_STL_VECTOR_H) || !defined(__SGI_STL_MAP_H) || !defined(__SGI_STL_MULTIMAP_H)

#include <vector>
#include <map>
#include <hash_map>
#include <stack>
#include <set>
#include <math.h> // prevent conflict between exception and std::exception

using namespace std;

#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif

//... namespace comphelper ................................................
namespace comphelper
{
//.........................................................................

//========================================================================
// comparisation functions

//------------------------------------------------------------------------
struct UStringLess : public binary_function< ::rtl::OUString, ::rtl::OUString, bool>
{
    bool operator() (const ::rtl::OUString& x, const ::rtl::OUString& y) const { return x < y ? true : false;}      // construct prevents a MSVC6 warning
};
//------------------------------------------------------------------------
struct UStringMixLess : public binary_function< ::rtl::OUString, ::rtl::OUString, bool>
{
    bool m_bCaseSensitive;
public:
    UStringMixLess(bool bCaseSensitive = true):m_bCaseSensitive(bCaseSensitive){}
    bool operator() (const ::rtl::OUString& x, const ::rtl::OUString& y) const
    {
        if (m_bCaseSensitive)
            return rtl_ustr_compare(x.getStr(), y.getStr()) < 0 ? true : false;
        else
            return rtl_ustr_compareIgnoreAsciiCase(x.getStr(), y.getStr()) < 0 ? true : false;
    }

    bool isCaseSensitive() const {return m_bCaseSensitive;}
};
//------------------------------------------------------------------------
struct UStringEqual
{
    sal_Bool operator() (const ::rtl::OUString& lhs, const ::rtl::OUString& rhs) const { return lhs.equals( rhs );}
};

//------------------------------------------------------------------------
struct UStringIEqual
{
    sal_Bool operator() (const ::rtl::OUString& lhs, const ::rtl::OUString& rhs) const { return lhs.equalsIgnoreAsciiCase( rhs );}
};

//------------------------------------------------------------------------
struct UStringHash
{
    size_t operator() (const ::rtl::OUString& rStr) const {return rStr.hashCode();}
};

//------------------------------------------------------------------------
class UStringMixEqual
{
    sal_Bool m_bCaseSensitive;

public:
    UStringMixEqual(sal_Bool bCaseSensitive = sal_True):m_bCaseSensitive(bCaseSensitive){}
    sal_Bool operator() (const ::rtl::OUString& lhs, const ::rtl::OUString& rhs) const
    {
        return m_bCaseSensitive ? lhs.equals( rhs ) : lhs.equalsIgnoreAsciiCase( rhs );
    }
    sal_Bool isCaseSensitive() const {return m_bCaseSensitive;}
};

//------------------------------------------------------------------------
class UStringMixHash
{
    sal_Bool m_bCaseSensitive;

public:
    UStringMixHash(sal_Bool bCaseSensitive = sal_True):m_bCaseSensitive(bCaseSensitive){}
    size_t operator() (const ::rtl::OUString& rStr) const
    {
        return m_bCaseSensitive ? rStr.hashCode() : rStr.toAsciiUpperCase().hashCode();
    }
    sal_Bool isCaseSensitive() const {return m_bCaseSensitive;}
};

//=====================================================================
//= OInterfaceCompare
//=====================================================================
/** is stl-compliant structure for comparing Reference< <iface> > instances
*/
template < class IAFCE >
struct OInterfaceCompare
    :public ::std::binary_function  <   ::com::sun::star::uno::Reference< IAFCE >
                                    ,   ::com::sun::star::uno::Reference< IAFCE >
                                    ,   bool
                                    >
{
    bool operator() (const ::com::sun::star::uno::Reference< IAFCE >& lhs, const ::com::sun::star::uno::Reference< IAFCE >& rhs) const
    {
        return lhs.get() < rhs.get();
            // this does not make any sense if you see the semantics of the pointer returned by get:
            // It's a pointer to a point in memory where an interface implementation lies.
            // But for our purpose (provide a reliable less-operator which can be used with the STL), this is
            // sufficient ....
    }
};

//.........................................................................
}
//... namespace comphelper ................................................

//==================================================================
// consistently defining stl-types
//==================================================================

#define DECLARE_STL_ITERATORS(classname)                            \
    typedef classname::iterator         classname##Iterator;        \
    typedef classname::const_iterator   Const##classname##Iterator  \

#define DECLARE_STL_MAP(keytype, valuetype, comparefct, classname)  \
    typedef std::map< keytype, valuetype, comparefct >  classname;  \
    DECLARE_STL_ITERATORS(classname)                                \

#define DECLARE_STL_STDKEY_MAP(keytype, valuetype, classname)               \
    DECLARE_STL_MAP(keytype, valuetype, std::less< keytype >, classname)    \

#define DECLARE_STL_VECTOR(valuetyp, classname)     \
    typedef std::vector< valuetyp >     classname;  \
    DECLARE_STL_ITERATORS(classname)                \

#define DECLARE_STL_USTRINGACCESS_MAP(valuetype, classname)                 \
    DECLARE_STL_MAP(::rtl::OUString, valuetype, ::comphelper::UStringLess, classname)   \

#define DECLARE_STL_STDKEY_SET(valuetype, classname)    \
    typedef ::std::set< valuetype > classname;          \
    DECLARE_STL_ITERATORS(classname)                    \

#define DECLARE_STL_SET(valuetype, comparefct, classname)               \
    typedef ::std::set< valuetype, comparefct > classname;  \
    DECLARE_STL_ITERATORS(classname)                        \

#endif

#endif  // _COMPHELPER_STLTYPES_HXX_

<|endoftext|>