// Copyright (c) 2010 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 "update_engine/bzip.h"

#include <stdlib.h>
#include <algorithm>
#include <bzlib.h>
#include "update_engine/utils.h"

using std::string;
using std::vector;

namespace chromeos_update_engine {

namespace {

// BzipData compresses or decompresses the input to the output.
// Returns true on success.
// Use one of BzipBuffToBuff*ompress as the template parameter to BzipData().
int BzipBuffToBuffDecompress(char* out,
                             uint32_t* out_length,
                             const char* in,
                             uint32_t in_length) {
  return BZ2_bzBuffToBuffDecompress(out,
                                    out_length,
                                    const_cast<char*>(in),
                                    in_length,
                                    0,  // Silent verbosity
                                    0);  // Normal algorithm
}

int BzipBuffToBuffCompress(char* out,
                           uint32_t* out_length,
                           const char* in,
                           uint32_t in_length) {
  return BZ2_bzBuffToBuffCompress(out,
                                  out_length,
                                  const_cast<char*>(in),
                                  in_length,
                                  9,  // Best compression
                                  0,  // Silent verbosity
                                  0);  // Default work factor
}

template<int F(char* out,
               uint32_t* out_length,
               const char* in,
               uint32_t in_length)>
bool BzipData(const char* const in,
              const int32_t in_size,
              vector<char>* const out) {
  TEST_AND_RETURN_FALSE(out);
  out->clear();
  if (in_size == 0) {
    return true;
  }
  // Try increasing buffer size until it works
  size_t buf_size = in_size;
  out->resize(buf_size);

  for (;;) {
    uint32_t data_size = buf_size;
    int rc = F(&(*out)[0], &data_size, in, in_size);
    TEST_AND_RETURN_FALSE(rc == BZ_OUTBUFF_FULL || rc == BZ_OK);
    if (rc == BZ_OK) {
      // we're done!
      out->resize(data_size);
      return true;
    }

    // Data didn't fit; double the buffer size.
    buf_size *= 2;
    out->resize(buf_size);
  }
}

}  // namespace

bool BzipDecompress(const vector<char>& in, vector<char>* out) {
  return BzipData<BzipBuffToBuffDecompress>(&in[0],
                                            static_cast<int32_t>(in.size()),
                                            out);
}

bool BzipCompress(const vector<char>& in, vector<char>* out) {
  return BzipData<BzipBuffToBuffCompress>(&in[0], in.size(), out);
}

namespace {
template<bool F(const char* const in,
                const int32_t in_size,
                vector<char>* const out)>
bool BzipString(const string& str,
                vector<char>* out) {
  TEST_AND_RETURN_FALSE(out);
  vector<char> temp;
  TEST_AND_RETURN_FALSE(F(str.data(),
                          str.size(),
                          &temp));
  out->clear();
  out->insert(out->end(), temp.begin(), temp.end());
  return true;
}
}  // namespace

bool BzipCompressString(const string& str,
                        vector<char>* out) {
  return BzipString<BzipData<BzipBuffToBuffCompress>>(str, out);
}

bool BzipDecompressString(const string& str,
                          vector<char>* out) {
  return BzipString<BzipData<BzipBuffToBuffDecompress>>(str, out);
}

}  // namespace chromeos_update_engine
