// Copyright 2017 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 "bsdiff/endsley_patch_writer.h"

#include <string.h>

#include <algorithm>

#include "bsdiff/brotli_compressor.h"
#include "bsdiff/bz2_compressor.h"
#include "bsdiff/logging.h"

namespace {

constexpr uint8_t kEndsleyMagicHeader[] = "ENDSLEY/BSDIFF43";

void EncodeInt64(int64_t x, uint8_t* buf) {
  uint64_t y = x < 0 ? (1ULL << 63ULL) - x : x;
  for (int i = 0; i < 8; ++i) {
    buf[i] = y & 0xff;
    y /= 256;
  }
}

// The minimum size that we would consider flushing out.
constexpr size_t kMinimumFlushSize = 1024 * 1024;  // 1 MiB

}  // namespace

namespace bsdiff {

bool EndsleyPatchWriter::Init(size_t new_size) {
  switch (compressor_type_) {
    case CompressorType::kNoCompression:
      // The patch is uncompressed and it will need exactly:
      //   new_size + 24 * len(control_entries) + sizeof(header)
      // We don't know the length of the control entries yet, but we can reserve
      // enough space to hold at least |new_size|.
      patch_->clear();
      patch_->reserve(new_size);
      break;
    case CompressorType::kBrotli:
      compressor_.reset(new BrotliCompressor(brotli_quality_));
      if (!compressor_) {
        LOG(ERROR) << "Error creating brotli compressor.";
        return false;
      }
      break;
    case CompressorType::kBZ2:
      compressor_.reset(new BZ2Compressor());
      if (!compressor_) {
        LOG(ERROR) << "Error creating BZ2 compressor.";
        return false;
      }
      break;
  }

  // Header is the magic followed by the new length.
  uint8_t header[24];
  memcpy(header, kEndsleyMagicHeader, 16);
  EncodeInt64(new_size, header + 16);
  EmitBuffer(header, sizeof(header));
  return true;
}

bool EndsleyPatchWriter::WriteDiffStream(const uint8_t* data, size_t size) {
  if (!size)
    return true;
  // Speed-up the common case where the diff stream data is added right after
  // the control entry that refers to it.
  if (control_.empty() && pending_diff_ >= size) {
    pending_diff_ -= size;
    EmitBuffer(data, size);
    return true;
  }

  diff_data_.insert(diff_data_.end(), data, data + size);
  return true;
}

bool EndsleyPatchWriter::WriteExtraStream(const uint8_t* data, size_t size) {
  if (!size)
    return true;
  // Speed-up the common case where the extra stream data is added right after
  // the diff stream data and the control entry that refers to it. Note that
  // the diff data comes first so we need to make sure it is all out.
  if (control_.empty() && !pending_diff_ && pending_extra_ >= size) {
    pending_extra_ -= size;
    EmitBuffer(data, size);
    return true;
  }

  extra_data_.insert(extra_data_.end(), data, data + size);
  return true;
}

bool EndsleyPatchWriter::AddControlEntry(const ControlEntry& entry) {
  // Speed-up the common case where the control entry is added when there's
  // nothing else pending.
  if (control_.empty() && diff_data_.empty() && extra_data_.empty() &&
      !pending_diff_ && !pending_extra_) {
    pending_diff_ = entry.diff_size;
    pending_extra_ = entry.extra_size;
    EmitControlEntry(entry);
    return true;
  }

  control_.push_back(entry);
  pending_control_data_ += entry.diff_size + entry.extra_size;

  // Check whether it is worth Flushing the entries now that the we have more
  // control entries. We need control entries to write enough output data, and
  // we need that output data to be at least 50% of the available diff and extra
  // data. This last requirement is to reduce the overhead of removing the
  // flushed data.
  if (pending_control_data_ > kMinimumFlushSize &&
      (diff_data_.size() + extra_data_.size()) / 2 <= pending_control_data_) {
    Flush();
  }

  return true;
}

bool EndsleyPatchWriter::Close() {
  // Flush any pending data.
  Flush();

  if (pending_diff_ || pending_extra_ || !control_.empty()) {
    LOG(ERROR) << "Insufficient data sent to diff/extra streams";
    return false;
  }

  if (!diff_data_.empty() || !extra_data_.empty()) {
    LOG(ERROR) << "Pending data to diff/extra not flushed out on Close()";
    return false;
  }

  if (compressor_) {
    if (!compressor_->Finish())
      return false;
    *patch_ = compressor_->GetCompressedData();
  }

  return true;
}

void EndsleyPatchWriter::EmitControlEntry(const ControlEntry& entry) {
  // Generate the 24 byte control entry.
  uint8_t buf[24];
  EncodeInt64(entry.diff_size, buf);
  EncodeInt64(entry.extra_size, buf + 8);
  EncodeInt64(entry.offset_increment, buf + 16);
  EmitBuffer(buf, sizeof(buf));
}

void EndsleyPatchWriter::EmitBuffer(const uint8_t* data, size_t size) {
  if (compressor_) {
    compressor_->Write(data, size);
  } else {
    patch_->insert(patch_->end(), data, data + size);
  }
}

void EndsleyPatchWriter::Flush() {
  size_t used_diff = 0;
  size_t used_extra = 0;
  size_t used_control = 0;
  do {
    if (!pending_diff_ && !pending_extra_ && used_control < control_.size()) {
      // We can emit a control entry in these conditions.
      const ControlEntry& entry = control_[used_control];
      used_control++;

      pending_diff_ = entry.diff_size;
      pending_extra_ = entry.extra_size;
      pending_control_data_ -= entry.extra_size + entry.diff_size;
      EmitControlEntry(entry);
    }

    if (pending_diff_) {
      size_t diff_size = std::min(diff_data_.size() - used_diff, pending_diff_);
      EmitBuffer(diff_data_.data() + used_diff, diff_size);
      pending_diff_ -= diff_size;
      used_diff += diff_size;
    }

    if (!pending_diff_ && pending_extra_) {
      size_t extra_size =
          std::min(extra_data_.size() - used_extra, pending_extra_);
      EmitBuffer(extra_data_.data() + used_extra, extra_size);
      pending_extra_ -= extra_size;
      used_extra += extra_size;
    }
  } while (!pending_diff_ && !pending_extra_ && used_control < control_.size());

  if (used_diff)
    diff_data_.erase(diff_data_.begin(), diff_data_.begin() + used_diff);
  if (used_extra)
    extra_data_.erase(extra_data_.begin(), extra_data_.begin() + used_extra);
  if (used_control)
    control_.erase(control_.begin(), control_.begin() + used_control);
}

}  // namespace bsdiff
