/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * 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 "xz_utils.h"

#include <vector>
#include <mutex>

#include "base/array_ref.h"
#include "base/bit_utils.h"
#include "base/leb128.h"
#include "base/mem_map.h"
#include "dwarf/writer.h"

// liblzma.
#include "7zCrc.h"
#include "Xz.h"
#include "XzCrc64.h"
#include "XzEnc.h"

namespace art {

static void XzInitCrc() {
  static std::once_flag crc_initialized;
  std::call_once(crc_initialized, []() {
    CrcGenerateTable();
    Crc64GenerateTable();
  });
}

void XzCompress(ArrayRef<const uint8_t> src,
                std::vector<uint8_t>* dst,
                int level,
                size_t block_size) {
  // Configure the compression library.
  XzInitCrc();
  CLzma2EncProps lzma2Props;
  Lzma2EncProps_Init(&lzma2Props);
  lzma2Props.lzmaProps.level = level;
  lzma2Props.lzmaProps.reduceSize = src.size();  // Size of data that will be compressed.
  lzma2Props.blockSize = block_size;
  Lzma2EncProps_Normalize(&lzma2Props);
  CXzProps props;
  XzProps_Init(&props);
  props.lzma2Props = lzma2Props;
  // Implement the required interface for communication (written in C so no virtual methods).
  struct XzCallbacks : public ISeqInStream, public ISeqOutStream, public ICompressProgress {
    static SRes ReadImpl(const ISeqInStream* p, void* buf, size_t* size) {
      auto* ctx = static_cast<XzCallbacks*>(const_cast<ISeqInStream*>(p));
      *size = std::min(*size, ctx->src_.size() - ctx->src_pos_);
      memcpy(buf, ctx->src_.data() + ctx->src_pos_, *size);
      ctx->src_pos_ += *size;
      return SZ_OK;
    }
    static size_t WriteImpl(const ISeqOutStream* p, const void* buf, size_t size) {
      auto* ctx = static_cast<const XzCallbacks*>(p);
      const uint8_t* buffer = reinterpret_cast<const uint8_t*>(buf);
      ctx->dst_->insert(ctx->dst_->end(), buffer, buffer + size);
      return size;
    }
    static SRes ProgressImpl(const ICompressProgress* , UInt64, UInt64) {
      return SZ_OK;
    }
    size_t src_pos_;
    ArrayRef<const uint8_t> src_;
    std::vector<uint8_t>* dst_;
  };
  XzCallbacks callbacks;
  callbacks.Read = XzCallbacks::ReadImpl;
  callbacks.Write = XzCallbacks::WriteImpl;
  callbacks.Progress = XzCallbacks::ProgressImpl;
  callbacks.src_pos_ = 0;
  callbacks.src_ = src;
  callbacks.dst_ = dst;
  // Compress.
  SRes res = Xz_Encode(&callbacks, &callbacks, &props, &callbacks);
  CHECK_EQ(res, SZ_OK);

  // Decompress the data back and check that we get the original.
  if (kIsDebugBuild) {
    std::vector<uint8_t> decompressed;
    XzDecompress(ArrayRef<const uint8_t>(*dst), &decompressed);
    DCHECK_EQ(decompressed.size(), src.size());
    DCHECK_EQ(memcmp(decompressed.data(), src.data(), src.size()), 0);
  }
}

void XzDecompress(ArrayRef<const uint8_t> src, std::vector<uint8_t>* dst) {
  const size_t page_size = MemMap::GetPageSize();

  XzInitCrc();
  std::unique_ptr<CXzUnpacker> state(new CXzUnpacker());
  ISzAlloc alloc;
  alloc.Alloc = [](ISzAllocPtr, size_t size) { return malloc(size); };
  alloc.Free = [](ISzAllocPtr, void* ptr) { return free(ptr); };
  XzUnpacker_Construct(state.get(), &alloc);

  size_t src_offset = 0;
  size_t dst_offset = 0;
  ECoderStatus status;
  do {
    dst->resize(RoundUp(dst_offset + page_size / 4, page_size));
    size_t src_remaining = src.size() - src_offset;
    size_t dst_remaining = dst->size() - dst_offset;
    int return_val = XzUnpacker_Code(state.get(),
                                     dst->data() + dst_offset,
                                     &dst_remaining,
                                     src.data() + src_offset,
                                     &src_remaining,
                                     true,
                                     CODER_FINISH_ANY,
                                     &status);
    CHECK_EQ(return_val, SZ_OK);
    src_offset += src_remaining;
    dst_offset += dst_remaining;
  } while (status == CODER_STATUS_NOT_FINISHED);
  CHECK_EQ(src_offset, src.size());
  CHECK(XzUnpacker_IsStreamWasFinished(state.get()));
  XzUnpacker_Free(state.get());
  dst->resize(dst_offset);
}

}  // namespace art
