/*
 * Copyright 2014 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "securemessage/byte_buffer.h"

#include <climits>
#include <cstring>

#include <iomanip>
#include <sstream>

using std::vector;

namespace securemessage {

ByteBuffer::ByteBuffer() {
  // Do nothing
}

ByteBuffer::~ByteBuffer() { Wipe(); }

ByteBuffer::ByteBuffer(const size_t size) {
  // Fills the data buffer with size number of zeros
  data_.resize(size, 0);
}

void ByteBuffer::SetData(const uint8_t* source_data, const size_t length) {
  // reserve() might cause re-allocation, so we wipe first.
  Wipe();
  data_.clear();

  data_.resize(length);
  for (size_t i = 0; i < length; i++) {
    data_[i] = source_data[i];
  }
}

void ByteBuffer::Append(const size_t num_bytes, const uint8_t byte) {
  // harmless on size_t overflow, but might cause reallocation which might leak
  // data on the heap
  data_.reserve(data_.size() + num_bytes);
  data_.insert(data_.end(), num_bytes, byte);
}

void ByteBuffer::Prepend(const string& str) {
  // might cause reallocation which might leak data on the heap
  data_.insert(data_.begin(), str.begin(), str.end());
}

ByteBuffer ByteBuffer::Concat(const ByteBuffer& a, const ByteBuffer& b) {
  // We assume compiler implements NRVO here.  We avoid initializing
  // return_value via a.Copy() because reserve() may result in another
  // data copy, which we are trying to eliminate in the first place.
  ByteBuffer return_value;

  return_value.data_.reserve(a.size() + b.size());  // harmless on overflow
  return_value.data_.insert(return_value.data_.end(), a.data_.begin(),
                            a.data_.end());
  return_value.data_.insert(return_value.data_.end(), b.data_.begin(),
                            b.data_.end());
  return return_value;
}

// GCC before 4.7 doesn't support delegated constructors, so we can't be as
// elegant as we could otherwise.
ByteBuffer::ByteBuffer(const uint8_t* source_data, const size_t length) {
  SetData(source_data, length);
}

ByteBuffer::ByteBuffer(const char* source_data) {
  SetData(reinterpret_cast<const uint8_t*>(source_data), strlen(source_data));
}

ByteBuffer::ByteBuffer(const char* source_data, const size_t length) {
  SetData(reinterpret_cast<const uint8_t*>(source_data), length);
}

ByteBuffer::ByteBuffer(const string& source_data) {
  SetData(reinterpret_cast<const uint8_t*>(source_data.c_str()),
          source_data.length());
}

size_t ByteBuffer::size() const { return data_.size(); }

std::unique_ptr<ByteBuffer> ByteBuffer::SubArray(const size_t offset,
                                                 const size_t length) const {
  if (length == 0) {
    return std::unique_ptr<ByteBuffer>(new ByteBuffer());
  }

  // Overflow check
  if (length > UINT_MAX - offset) {
    return nullptr;
  }

  // Bounds check
  if (offset + length > size()) {
    return nullptr;
  }

  return std::unique_ptr<ByteBuffer>(
      new ByteBuffer(ImmutableUChar() + offset, length));
}

unsigned char* ByteBuffer::MutableUChar() {
  return reinterpret_cast<unsigned char*>(MutableUInt8());
}

unsigned const char* ByteBuffer::ImmutableUChar() const {
  return reinterpret_cast<unsigned const char*>(data_.data());
}

uint8_t* ByteBuffer::MutableUInt8() { return data_.data(); }

const uint8_t* ByteBuffer::ImmutableUInt8() const {
  return reinterpret_cast<const uint8_t*>(data_.data());
}

string ByteBuffer::String() const {
  return string(reinterpret_cast<const char*>(data_.data()), data_.size());
}

vector<uint8_t> ByteBuffer::Vector() const { return vector<uint8_t>(data_); }

bool ByteBuffer::Equals(const ByteBuffer& other) const {
  if (other.size() != size()) {
    return false;
  }

  // Make sure to always iterate over all elements to defeat timing attacks
  unsigned int result = 0;
  for (size_t i = 0; i < size(); i++) {
    result |= data_[i] ^ other.ImmutableUInt8()[i];
  }

  return (result == 0);
}

string ByteBuffer::AsDebugHexString() const {
  if (data_.size() == 0) {
    return string();
  }

  const char hex[] = "0123456789abcdef";
  string result = string("0x");

  for (size_t i = 0; i < data_.size(); i++) {
    result.push_back(hex[0xf & (data_[i] >> 4)]);
    result.push_back(hex[0xf & data_[i]]);
  }

  return result;
}

void ByteBuffer::Clear() {
  Wipe();
  data_.clear();
}

void ByteBuffer::Wipe() { WipeBuffer(data_.data(), data_.size()); }

void ByteBuffer::WipeBuffer(uint8_t* buffer, const size_t length) {
  volatile uint8_t* byte_to_wipe = buffer;
  for (size_t i = 0; i < length; i++) {
    byte_to_wipe[i] = 0;
  }
}

}  // namespace securemessage
