/*
 * Copyright 2017 Google Inc. All Rights Reserved.
 *
 * 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 "starboard/client_porting/poem/string_leaks_poem.h"

#include "nb/hash.h"
#include "nb/string_interner.h"
#include "starboard/client_porting/poem/string_poem.h"
#include "starboard/string.h"

namespace nb {

StringInterner::StringInterner() {
}

StringInterner::~StringInterner() {
}

const std::string& StringInterner::Intern(const std::string& str) {
  starboard::ScopedLock lock(mutex_);
  return Intern_Locked(str);
}

const std::string& StringInterner::Intern(const char* c_string) {
  starboard::ScopedLock lock(mutex_);
  scratch_.assign(c_string);  // Good at recycling memory.
  return Intern_Locked(scratch_);
}

const std::string* StringInterner::Get(const std::string& str) const {
  starboard::ScopedLock lock(mutex_);
  return Get_Locked(str);
}

const std::string* StringInterner::Get(const char* c_string) const {
  starboard::ScopedLock lock(mutex_);
  scratch_.assign(c_string);  // Good at recycling memory.
  return Get_Locked(scratch_);
}

const std::string* StringInterner::Get_Locked(const std::string& str) const {
  std::set<std::string>::const_iterator it = string_set_.find(str);
  if (it == string_set_.end()) {
    return NULL;
  } else {
    const std::string& out = *it;
    return &out;
  }
}

size_t StringInterner::Size() const {
  starboard::ScopedLock lock(mutex_);
  return string_set_.size();
}

const std::string& StringInterner::Intern_Locked(const std::string& str) {
  std::set<std::string>::const_iterator it = string_set_.insert(str).first;
  const std::string& out = (*it);
  // Safe because std::set does not invalidate iterators on insert or when
  // erasing other iterators.
  return out;
}

ConcurrentStringInterner::ConcurrentStringInterner(size_t table_size) {
  Construct(table_size);
}

void ConcurrentStringInterner::Construct(size_t table_size) {
  if (table_size == 0) {
    table_size = 1;
  }
  string_interner_table_.reserve(table_size);
  for (size_t i = 0; i < table_size; ++i) {
    string_interner_table_.push_back(new StringInterner);
  }
}

ConcurrentStringInterner::~ConcurrentStringInterner() {
  for (size_t i = 0; i < string_interner_table_.size(); ++i) {
    delete string_interner_table_[i];
  }
}

const std::string& ConcurrentStringInterner::Intern(const std::string& str) {
  return GetBucket(str.c_str(), str.size()).Intern(str);
}

const std::string& ConcurrentStringInterner::Intern(const char* c_string) {
  return GetBucket(c_string, SbStringGetLength(c_string)).Intern(c_string);
}

const std::string* ConcurrentStringInterner::Get(const std::string& str) const {
  return GetBucket(str.c_str(), str.size()).Get(str);
}

const std::string* ConcurrentStringInterner::Get(const char* c_string) const {
  return GetBucket(c_string, SbStringGetLength(c_string)).Get(c_string);
}

size_t ConcurrentStringInterner::Size() const {
  size_t sum = 0;
  for (size_t i = 0; i < string_interner_table_.size(); ++i) {
    sum += string_interner_table_[i]->Size();
  }
  return sum;
}

nb::StringInterner&
ConcurrentStringInterner::GetBucket(const char* string, size_t n) {
  uint32_t hash_value = nb::RuntimeHash32(string, static_cast<int>(n));
  size_t index =
    static_cast<size_t>(hash_value % string_interner_table_.size());
  return *string_interner_table_[index];
}

const nb::StringInterner&
ConcurrentStringInterner::GetBucket(const char* string, size_t n) const {
  uint32_t hash_value = nb::RuntimeHash32(string, static_cast<int>(n));
  size_t index =
    static_cast<size_t>(hash_value % string_interner_table_.size());
  return *string_interner_table_[index];
}

 }  // namespace nb
