// Copyright 2017 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 <string.h>
#include <zircon/assert.h>

#include <atomic>
#include <new>

#include <fbl/algorithm.h>
#include <fbl/string.h>

namespace fbl {
namespace {

size_t SumLengths(const String* begin, const String* end, const String** last_non_empty_string) {
  size_t total_length = 0U;
  for (const String* it = begin; it != end; it++) {
    if (!it->empty()) {
      *last_non_empty_string = it;
      total_length += it->length();
    }
  }
  return total_length;
}

void Concat(char* data, const String* begin, const String* end) {
  for (const String* it = begin; it != end; it++) {
    memcpy(data, it->data(), it->length());
    data += it->length();
  }
  *data = 0;
}

}  // namespace

String::EmptyBuffer String::gEmpty;

void String::clear() {
  ReleaseRef(data_);
  InitWithEmpty();
}

int String::compare(const String& other) const {
  size_t len = std::min(length(), other.length());
  int retval = memcmp(data(), other.data(), len);
  if (retval == 0) {
    if (length() == other.length()) {
      return 0;
    }
    return length() < other.length() ? -1 : 1;
  }
  return retval;
}

void String::swap(String& other) {
  char* temp_data = data_;
  data_ = other.data_;
  other.data_ = temp_data;
}

String& String::operator=(const String& other) {
  AcquireRef(other.data_);
  ReleaseRef(data_);  // release after acquire in case other == *this
  data_ = other.data_;
  return *this;
}

String& String::operator=(String&& other) noexcept {
  ReleaseRef(data_);
  data_ = other.data_;
  other.InitWithEmpty();
  return *this;
}

void String::Set(const char* data, size_t length) {
  char* temp_data = data_;
  Init(data, length);
  ReleaseRef(temp_data);  // release after init in case data is within data_
}

void String::Set(const char* data, size_t length, fbl::AllocChecker* ac) {
  char* temp_data = data_;
  Init(data, length, ac);
  ReleaseRef(temp_data);  // release after init in case data is within data_
}

String String::Concat(std::initializer_list<String> strings) {
  const String* last_non_empty_string = nullptr;
  size_t total_length = SumLengths(strings.begin(), strings.end(), &last_non_empty_string);
  if (last_non_empty_string == nullptr) {
    return String();
  }
  if (total_length == last_non_empty_string->length()) {
    return *last_non_empty_string;
  }

  char* data = AllocData(total_length);

  fbl::Concat(data, strings.begin(), last_non_empty_string + 1);
  return String(data, nullptr);
}

String String::Concat(std::initializer_list<String> strings, AllocChecker* ac) {
  const String* last_non_empty_string = nullptr;
  size_t total_length = SumLengths(strings.begin(), strings.end(), &last_non_empty_string);
  if (last_non_empty_string == nullptr) {
    ac->arm(0U, true);
    return String();
  }
  if (total_length == last_non_empty_string->length()) {
    ac->arm(0U, true);
    return *last_non_empty_string;
  }

  char* data = AllocData(total_length, ac);
  if (!data) {
    return String();
  }

  fbl::Concat(data, strings.begin(), last_non_empty_string + 1);
  return String(data, nullptr);
}

void String::Init(const char* data, size_t length) {
  if (length == 0U) {
    InitWithEmpty();
    return;
  }

  data_ = AllocData(length);
  memcpy(data_, data, length);
  data_[length] = 0U;
}

void String::Init(const char* data, size_t length, AllocChecker* ac) {
  if (length == 0U) {
    ac->arm(0U, true);
    InitWithEmpty();
    return;
  }

  data_ = AllocData(length, ac);
  if (!data_) {
    InitWithEmpty();
    return;
  }
  memcpy(data_, data, length);
  data_[length] = 0U;
}

void String::Init(size_t count, char ch) {
  if (count == 0U) {
    InitWithEmpty();
    return;
  }

  data_ = AllocData(count);
  memset(data_, ch, count);
  data_[count] = 0U;
}

void String::Init(size_t count, char ch, AllocChecker* ac) {
  if (count == 0U) {
    ac->arm(0U, true);
    InitWithEmpty();
    return;
  }

  data_ = AllocData(count, ac);
  if (!data_) {
    InitWithEmpty();
    return;
  }
  memset(data_, ch, count);
  data_[count] = 0U;
}

void String::InitWithEmpty() {
  gEmpty.ref_count.fetch_add(1U, std::memory_order_relaxed);
  data_ = &gEmpty.nul;
}

char* String::AllocData(size_t length) {
  void* buffer = operator new(buffer_size(length));
  return InitData(buffer, length);
}

char* String::AllocData(size_t length, AllocChecker* ac) {
  void* buffer = operator new(buffer_size(length), ac);
  if (!buffer)
    return nullptr;
  return InitData(buffer, length);
}

char* String::InitData(void* buffer, size_t length) {
  char* data = static_cast<char*>(buffer) + kDataFieldOffset;
  *length_field_of(data) = length;
  new (ref_count_field_of(data)) std::atomic_uint(1U);
  return data;
}

void String::AcquireRef(char* data) {
  ref_count_field_of(data)->fetch_add(1U, std::memory_order_relaxed);
}

void String::ReleaseRef(char* data) {
  unsigned int prior_count = ref_count_field_of(data)->fetch_sub(1U, std::memory_order_release);
  ZX_DEBUG_ASSERT(prior_count != 0U);
  if (prior_count == 1U) {
    atomic_thread_fence(std::memory_order_acquire);
    operator delete(data - kDataFieldOffset);
  }
}

bool operator==(const String& lhs, const String& rhs) {
  return lhs.length() == rhs.length() && memcmp(lhs.data(), rhs.data(), lhs.length()) == 0;
}

}  // namespace fbl
