// Copyright 2019 The Fuchsia 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 "tools/kazoo/string_util.h"

#include <errno.h>
#include <stdarg.h>
#include <zircon/assert.h>

#include <memory>

namespace {

void StringVAppendfHelper(std::string* dest, const char* format, va_list ap) {
  // Size of the small stack buffer to use first. This should be kept in sync
  // with the numbers in StringPrintfTest.StringPrintf_Boundary.
  constexpr size_t kStackBufferSize = 1024u;

  // First, try with a small buffer on the stack.
  char stack_buf[kStackBufferSize];
  // Copy |ap| (which can only be used once), in case we need to retry.
  va_list ap_copy;
  va_copy(ap_copy, ap);
  int result = vsnprintf(stack_buf, kStackBufferSize, format, ap_copy);
  va_end(ap_copy);
  if (result < 0) {
    // As far as I can tell, we'd only get |EOVERFLOW| if the result is so large
    // that it can't be represented by an |int| (in which case retrying would be
    // futile), so Chromium's implementation is wrong.
    ZX_ASSERT(false);
    return;
  }
  // |result| should be the number of characters we need, not including the
  // terminating null. However, |vsnprintf()| always null-terminates!
  size_t output_size = static_cast<size_t>(result);
  // Check if the output fit into our stack buffer. This is "<" not "<=", since
  // |vsnprintf()| will null-terminate.
  if (output_size < kStackBufferSize) {
    // It fit.
    dest->append(stack_buf, static_cast<size_t>(result));
    return;
  }

  // Since we have the required output size, we can just heap allocate that.
  // (Add 1 because |vsnprintf()| will always null-terminate.)
  size_t heap_buf_size = output_size + 1u;
  std::unique_ptr<char[]> heap_buf(new char[heap_buf_size]);
  result = vsnprintf(heap_buf.get(), heap_buf_size, format, ap);
  if (result < 0 || static_cast<size_t>(result) > output_size) {
    ZX_ASSERT(false);
    return;
  }
  ZX_ASSERT(static_cast<size_t>(result) == output_size);
  dest->append(heap_buf.get(), static_cast<size_t>(result));
}

}  // namespace

bool ReadFileToString(const std::string& path, std::string* result) {
  FILE* fp = fopen(path.c_str(), "rb");
  if (!fp) {
    return false;
  }
  fseek(fp, 0, SEEK_END);
  result->resize(ftell(fp));
  rewind(fp);
  fread(&(*result)[0], 1, result->size(), fp);
  fclose(fp);
  return true;
}

std::string StringPrintf(const char* format, ...) {
  va_list ap;
  va_start(ap, format);
  std::string rv;
  StringVAppendfHelper(&rv, format, ap);
  va_end(ap);
  return rv;
}

std::string StringVPrintf(const char* format, va_list ap) {
  std::string rv;
  StringVAppendfHelper(&rv, format, ap);
  return rv;
}

std::string TrimString(const std::string& str, const std::string& chars_to_trim) {
  size_t start_index = str.find_first_not_of(chars_to_trim);
  if (start_index == std::string::npos) {
    return std::string();
  }
  size_t end_index = str.find_last_not_of(chars_to_trim);
  return str.substr(start_index, end_index - start_index + 1);
}

std::vector<std::string> SplitString(const std::string& input, char delimiter,
                                     WhitespaceHandling whitespace) {
  std::vector<std::string> result;

  auto start = input.begin();
  for (auto end = start; end != input.end(); start = end + 1) {
    end = start;
    while (end != input.end() && *end != delimiter) {
      ++end;
    }
    if (whitespace == kKeepWhitespace) {
      result.push_back(std::string(start, end));
    } else {
      result.push_back(TrimString(std::string(start, end), " \t\r\n"));
    }
  }

  return result;
}

int64_t StringToInt(const std::string& str) {
  return static_cast<int64_t>(strtoll(str.c_str(), nullptr, 10));
}

uint64_t StringToUInt(const std::string& str) {
  return static_cast<uint64_t>(strtoull(str.c_str(), nullptr, 10));
}

bool StartsWith(const std::string& str, const std::string& prefix) {
  return str.compare(0, prefix.size(), prefix) == 0;
}
