/*
 * Copyright 2015 WebAssembly Community Group participants
 *
 * 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.
 */

// Interned String type, 100% interned on creation. Comparisons are always just
// a pointer comparison

#ifndef wasm_istring_h
#define wasm_istring_h

#include <set>
#include <unordered_map>
#include <unordered_set>

#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "support/threads.h"
#include "support/utilities.h"

namespace cashew {

struct IString {
  const char* str = nullptr;

  static size_t
  hash_c(const char* str) { // see http://www.cse.yorku.ca/~oz/hash.html
    unsigned int hash = 5381;
    int c;
    while ((c = *str++)) {
      hash = ((hash << 5) + hash) ^ c;
    }
    return (size_t)hash;
  }

  class CStringHash {
  public:
    size_t operator()(const char* str) const { return IString::hash_c(str); }
  };
  class CStringEqual {
  public:
    bool operator()(const char* x, const char* y) const {
      return strcmp(x, y) == 0;
    }
  };

  IString() = default;
  // if reuse=true, then input is assumed to remain alive; not copied
  IString(const char* s, bool reuse = true) {
    assert(s);
    set(s, reuse);
  }

  void set(const char* s, bool reuse = true) {
    typedef std::unordered_set<const char*, CStringHash, CStringEqual>
      StringSet;
    // one global store of strings per thread, we must not access this
    // in parallel
    thread_local static StringSet strings;

    auto existing = strings.find(s);

    if (existing == strings.end()) {
      // if the string isn't already known, we must use a single global
      // storage location, guarded by a mutex, so each string is allocated
      // exactly once
      static std::mutex mutex;
      std::unique_lock<std::mutex> lock(mutex);
      // a single global set contains the actual strings, so we allocate each
      // one exactly once.
      static StringSet globalStrings;
      auto globalExisting = globalStrings.find(s);
      if (globalExisting == globalStrings.end()) {
        if (!reuse) {
          static std::vector<std::unique_ptr<std::string>> allocated;
          allocated.emplace_back(wasm::make_unique<std::string>(s));
          s = allocated.back()->c_str(); // we'll never modify it, so this is ok
        }
        // insert into global set
        globalStrings.insert(s);
      } else {
        s = *globalExisting;
      }
      // add the string to our thread-local set
      strings.insert(s);
    } else {
      s = *existing;
    }

    str = s;
  }

  void set(const IString& s) { str = s.str; }

  void clear() { str = nullptr; }

  bool operator==(const IString& other) const {
    // assert((str == other.str) == !strcmp(str, other.str));
    return str == other.str; // fast!
  }
  bool operator!=(const IString& other) const {
    // assert((str == other.str) == !strcmp(str, other.str));
    return str != other.str; // fast!
  }
  bool operator<(const IString& other) const {
    return strcmp(str ? str : "", other.str ? other.str : "") < 0;
  }

  char operator[](int x) const { return str[x]; }

  bool operator!() const { // no string, or empty string
    return !str || str[0] == 0;
  }

  const char* c_str() const { return str; }
  bool equals(const char* other) const { return !strcmp(str, other); }

  bool is() const { return str != nullptr; }
  bool isNull() const { return str == nullptr; }

  const char* stripPrefix(const char* prefix) const {
    const char* ptr = str;
    while (true) {
      if (*prefix == 0) {
        return ptr;
      }
      if (*ptr == 0) {
        return nullptr;
      }
      if (*ptr++ != *prefix++) {
        return nullptr;
      }
    }
  }

  bool startsWith(const char* prefix) const {
    return stripPrefix(prefix) != nullptr;
  }
  bool startsWith(const IString& prefix) const {
    return startsWith(prefix.str);
  }

  size_t size() const { return str ? strlen(str) : 0; }
};

} // namespace cashew

// Utilities for creating hashmaps/sets over IStrings

namespace std {

template<> struct hash<cashew::IString> {
  size_t operator()(const cashew::IString& str) const {
    return std::hash<size_t>{}(size_t(str.str));
  }
};

template<> struct equal_to<cashew::IString> {
  bool operator()(const cashew::IString& x, const cashew::IString& y) const {
    return x == y;
  }
};

} // namespace std

namespace cashew {

// IStringSet

class IStringSet : public std::unordered_set<IString> {
  std::vector<char> data;

public:
  IStringSet() = default;
  IStringSet(const char* init) { // comma-delimited list
    int size = strlen(init) + 1;
    data.resize(size);
    char* curr = &data[0];
    strncpy(curr, init, size);
    while (1) {
      char* end = strchr(curr, ' ');
      if (end) {
        *end = 0;
      }
      insert(curr);
      if (!end) {
        break;
      }
      curr = end + 1;
    }
  }

  bool has(const IString& str) { return count(str) > 0; }
};

class IOrderedStringSet : public std::set<IString> {
public:
  bool has(const IString& str) { return count(str) > 0; }
};

} // namespace cashew

#endif // wasm_istring_h
