/*
 * Copyright 2011 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 "sfntly/data/byte_array.h"

#include <algorithm>

#include "sfntly/port/exception_type.h"

namespace sfntly {

const int32_t ByteArray::COPY_BUFFER_SIZE = 8192;

ByteArray::~ByteArray() {}

int32_t ByteArray::Length() { return filled_length_; }
int32_t ByteArray::Size() { return storage_length_; }

int32_t ByteArray::SetFilledLength(int32_t filled_length) {
  filled_length_ = std::min<int32_t>(filled_length, storage_length_);
  return filled_length_;
}

int32_t ByteArray::Get(int32_t index) {
  if (index < 0 || index >= Length())
    return -1;
  return InternalGet(index) & 0xff;
}

int32_t ByteArray::Get(int32_t index, ByteVector* b) {
  assert(b);
  return Get(index, &((*b)[0]), 0, b->size());
}

int32_t ByteArray::Get(int32_t index,
                       byte_t* b,
                       int32_t offset,
                       int32_t length) {
  assert(b);
  if (index < 0 || index >= filled_length_) {
    return 0;
  }
  int32_t actual_length = std::min<int32_t>(length, filled_length_ - index);
  return InternalGet(index, b, offset, actual_length);
}

void ByteArray::Put(int32_t index, byte_t b) {
  if (index < 0 || index >= Size()) {
#if defined (SFNTLY_NO_EXCEPTION)
    return;
#else
    throw IndexOutOfBoundException(
        "Attempt to write outside the bounds of the data");
#endif
  }
  InternalPut(index, b);
  filled_length_ = std::max<int32_t>(filled_length_, index + 1);
}

int32_t ByteArray::Put(int index, ByteVector* b) {
  assert(b);
  return Put(index, &((*b)[0]), 0, b->size());
}

int32_t ByteArray::Put(int32_t index,
                       byte_t* b,
                       int32_t offset,
                       int32_t length) {
  assert(b);
  if (index < 0 || index >= Size()) {
#if defined (SFNTLY_NO_EXCEPTION)
    return 0;
#else
    throw IndexOutOfBoundException(
        "Attempt to write outside the bounds of the data");
#endif
  }
  int32_t actual_length = std::min<int32_t>(length, Size() - index);
  int32_t bytes_written = InternalPut(index, b, offset, actual_length);
  filled_length_ = std::max<int32_t>(filled_length_, index + bytes_written);
  return bytes_written;
}

int32_t ByteArray::CopyTo(ByteArray* array) {
  return CopyTo(array, 0, Length());
}

int32_t ByteArray::CopyTo(ByteArray* array, int32_t offset, int32_t length) {
  return CopyTo(0, array, offset, length);
}

int32_t ByteArray::CopyTo(int32_t dst_offset, ByteArray* array,
                          int32_t src_offset, int32_t length) {
  assert(array);
  if (array->Size() < dst_offset + length) {  // insufficient space
    return -1;
  }

  ByteVector b(COPY_BUFFER_SIZE);
  int32_t bytes_read = 0;
  int32_t index = 0;
  int32_t remaining_length = length;
  int32_t buffer_length = std::min<int32_t>(COPY_BUFFER_SIZE, length);
  while ((bytes_read =
              Get(index + src_offset, &(b[0]), 0, buffer_length)) > 0) {
    int bytes_written = array->Put(index + dst_offset, &(b[0]), 0, bytes_read);
    UNREFERENCED_PARAMETER(bytes_written);
    index += bytes_read;
    remaining_length -= bytes_read;
    buffer_length = std::min<int32_t>(b.size(), remaining_length);
  }
  return index;
}

int32_t ByteArray::CopyTo(OutputStream* os) {
    return CopyTo(os, 0, Length());
}

int32_t ByteArray::CopyTo(OutputStream* os, int32_t offset, int32_t length) {
  ByteVector b(COPY_BUFFER_SIZE);
  int32_t bytes_read = 0;
  int32_t index = 0;
  int32_t buffer_length = std::min<int32_t>(COPY_BUFFER_SIZE, length);
  while ((bytes_read = Get(index + offset, &(b[0]), 0, buffer_length)) > 0) {
    os->Write(&b, 0, bytes_read);
    index += bytes_read;
    buffer_length = std::min<int32_t>(b.size(), length - index);
  }
  return index;
}

bool ByteArray::CopyFrom(InputStream* is, int32_t length) {
  ByteVector b(COPY_BUFFER_SIZE);
  int32_t bytes_read = 0;
  int32_t index = 0;
  int32_t buffer_length = std::min<int32_t>(COPY_BUFFER_SIZE, length);
  while ((bytes_read = is->Read(&b, 0, buffer_length)) > 0) {
    if (Put(index, &(b[0]), 0, bytes_read) != bytes_read) {
#if defined (SFNTLY_NO_EXCEPTION)
      return 0;
#else
      throw IOException("Error writing bytes.");
#endif
    }
    index += bytes_read;
    length -= bytes_read;
    buffer_length = std::min<int32_t>(b.size(), length);
  }
  return true;
}

bool ByteArray::CopyFrom(InputStream* is) {
  ByteVector b(COPY_BUFFER_SIZE);
  int32_t bytes_read = 0;
  int32_t index = 0;
  int32_t buffer_length = COPY_BUFFER_SIZE;
  while ((bytes_read = is->Read(&b, 0, buffer_length)) > 0) {
    if (Put(index, &b[0], 0, bytes_read) != bytes_read) {
#if defined (SFNTLY_NO_EXCEPTION)
      return 0;
#else
      throw IOException("Error writing bytes.");
#endif
    }
    index += bytes_read;
  }
  return true;
}

ByteArray::ByteArray(int32_t filled_length,
                     int32_t storage_length,
                     bool growable) {
  Init(filled_length, storage_length, growable);
}

ByteArray::ByteArray(int32_t filled_length, int32_t storage_length) {
  Init(filled_length, storage_length, false);
}

void ByteArray::Init(int32_t filled_length,
                     int32_t storage_length,
                     bool growable) {
  storage_length_ = storage_length;
  growable_ = growable;
  SetFilledLength(filled_length);
}

}  // namespace sfntly
