// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "shill/net/byte_string.h"

#include <netinet/in.h>
#include <string.h>

#include <algorithm>

#include <base/strings/string_number_conversions.h>

using std::distance;
using std::min;
using std::string;
using std::vector;

namespace shill {

ByteString::ByteString(const ByteString &b) {
  data_.assign(Vector::const_iterator(b.begin_), b.data_.end());
  begin_ = data_.begin();
}

ByteString &ByteString::operator=(const ByteString &b) {
  data_.assign(Vector::const_iterator(b.begin_), b.data_.end());
  begin_ = data_.begin();
  return *this;
}

unsigned char *ByteString::GetData() {
  return (GetLength() == 0) ? nullptr : &*begin_;
}

const unsigned char *ByteString::GetConstData() const {
  return (GetLength() == 0) ? nullptr : &*begin_;
}

size_t ByteString::GetLength() const {
  return distance(Vector::const_iterator(begin_), data_.end());
}

ByteString ByteString::GetSubstring(size_t offset, size_t length) const {
  if (offset > GetLength()) {
    offset = GetLength();
  }
  if (length > GetLength() - offset) {
    length = GetLength() - offset;
  }
  return ByteString(GetConstData() + offset, length);
}

// static
ByteString ByteString::CreateFromCPUUInt32(uint32_t val) {
  return ByteString(reinterpret_cast<unsigned char *>(&val), sizeof(val));
}

// static
ByteString ByteString::CreateFromNetUInt32(uint32_t val) {
  return CreateFromCPUUInt32(ntohl(val));
}

// static
ByteString ByteString::CreateFromHexString(const string &hex_string) {
  vector<uint8_t> bytes;
  if (!base::HexStringToBytes(hex_string, &bytes)) {
    return ByteString();
  }
  return ByteString(&bytes.front(), bytes.size());
}

bool ByteString::ConvertToCPUUInt32(uint32_t *val) const {
  if (val == nullptr || GetLength() != sizeof(*val)) {
    return false;
  }
  memcpy(val, GetConstData(), sizeof(*val));

  return true;
}

bool ByteString::ConvertToNetUInt32(uint32_t *val) const {
  if (!ConvertToCPUUInt32(val)) {
    return false;
  }
  *val = ntohl(*val);
  return true;
}

template <typename T>
bool ByteString::ConvertByteOrderAsUIntArray(T (*converter)(T)) {
  size_t length = GetLength();
  if ((length % sizeof(T)) != 0) {
    return false;
  }
  for (Vector::iterator i = begin_; i != data_.end(); i += sizeof(T)) {
    // Take care of word alignment.
    T val;
    memcpy(&val, &(*i), sizeof(T));
    val = converter(val);
    memcpy(&(*i), &val, sizeof(T));
  }
  return true;
}

bool ByteString::ConvertFromNetToCPUUInt32Array() {
  return ConvertByteOrderAsUIntArray(ntohl);
}

bool ByteString::ConvertFromCPUToNetUInt32Array() {
  return ConvertByteOrderAsUIntArray(htonl);
}

bool ByteString::IsZero() const {
  for (Vector::const_iterator i = begin_; i != data_.end(); ++i) {
    if (*i != 0) {
      return false;
    }
  }
  return true;
}

bool ByteString::BitwiseAnd(const ByteString &b) {
  if (GetLength() != b.GetLength()) {
    return false;
  }
  Vector::iterator lhs(begin_);
  Vector::const_iterator rhs(b.begin_);
  while (lhs != data_.end()) {
    *lhs++ &= *rhs++;
  }
  return true;
}

bool ByteString::BitwiseOr(const ByteString &b) {
  if (GetLength() != b.GetLength()) {
    return false;
  }
  Vector::iterator lhs(begin_);
  Vector::const_iterator rhs(b.begin_);
  while (lhs != data_.end()) {
    *lhs++ |= *rhs++;
  }
  return true;
}

void ByteString::BitwiseInvert() {
  for (Vector::iterator i = begin_; i != data_.end(); ++i) {
    *i = ~*i;
  }
}

bool ByteString::Equals(const ByteString &b) const {
  if (GetLength() != b.GetLength()) {
    return false;
  }
  Vector::const_iterator lhs(begin_);
  Vector::const_iterator rhs(b.begin_);
  while (lhs != data_.end()) {
    if (*lhs++ != *rhs++) {
      return false;
    }
  }
  return true;
}

void ByteString::Append(const ByteString &b) {
  // Save and reapply offset since |insert| may reallocate the memory and
  // invalidate the iterator.
  size_t offset = distance(data_.begin(), begin_);
  data_.insert(data_.end(), Vector::const_iterator(b.begin_), b.data_.end());
  begin_ = data_.begin() + offset;
}

void ByteString::Clear() {
  data_.clear();
  begin_ = data_.begin();
}

void ByteString::Resize(int size) {
  // Save and reapply offset since |resize| may reallocate the memory and
  // invalidate the iterator.
  size_t offset = distance(data_.begin(), begin_);
  data_.resize(size + offset, 0);
  begin_ = data_.begin() + offset;
}

string ByteString::HexEncode() const {
  return base::HexEncode(GetConstData(), GetLength());
}

void ByteString::RemovePrefix(size_t offset) {
  if (offset >= GetLength()) {
    begin_ = data_.end();
  } else {
    begin_ += offset;
  }
}

// static
bool ByteString::IsLessThan(const ByteString &lhs, const ByteString &rhs) {
  size_t byte_count = min(lhs.GetLength(), rhs.GetLength());
  int result = memcmp(lhs.GetConstData(), rhs.GetConstData(), byte_count);
  if (result == 0) {
    return lhs.GetLength() < rhs.GetLength();
  }
  return result < 0;
}

}  // namespace shill
