// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_INSPECTOR_STRING_16_H_
#define V8_INSPECTOR_STRING_16_H_

#include <stdint.h>
#include <cctype>
#include <climits>
#include <cstring>
#include <string>
#include <vector>

#include "../../third_party/inspector_protocol/crdtp/serializer_traits.h"
#include "src/base/compiler-specific.h"

namespace v8_inspector {

using UChar = uint16_t;

class String16 {
 public:
  static const size_t kNotFound = static_cast<size_t>(-1);

  String16() = default;
  String16(const String16&) V8_NOEXCEPT = default;
  String16(String16&&) V8_NOEXCEPT = default;
  String16(const UChar* characters, size_t size);
  V8_EXPORT String16(const UChar* characters);  // NOLINT(runtime/explicit)
  V8_EXPORT String16(const char* characters);   // NOLINT(runtime/explicit)
  String16(const char* characters, size_t size);
  explicit String16(const std::basic_string<UChar>& impl);
  explicit String16(std::basic_string<UChar>&& impl);

  String16& operator=(const String16&) V8_NOEXCEPT = default;
  String16& operator=(String16&&) V8_NOEXCEPT = default;

  static String16 fromInteger(int);
  static String16 fromInteger(size_t);
  static String16 fromInteger64(int64_t);
  static String16 fromUInt64(uint64_t);
  static String16 fromDouble(double);
  static String16 fromDouble(double, int precision);

  int64_t toInteger64(bool* ok = nullptr) const;
  uint64_t toUInt64(bool* ok = nullptr) const;
  int toInteger(bool* ok = nullptr) const;
  String16 stripWhiteSpace() const;
  const UChar* characters16() const { return m_impl.c_str(); }
  size_t length() const { return m_impl.length(); }
  bool isEmpty() const { return !m_impl.length(); }
  UChar operator[](size_t index) const { return m_impl[index]; }
  String16 substring(size_t pos, size_t len = UINT_MAX) const {
    return String16(m_impl.substr(pos, len));
  }
  size_t find(const String16& str, size_t start = 0) const {
    return m_impl.find(str.m_impl, start);
  }
  size_t reverseFind(const String16& str, size_t start = UINT_MAX) const {
    return m_impl.rfind(str.m_impl, start);
  }
  size_t find(UChar c, size_t start = 0) const { return m_impl.find(c, start); }
  size_t reverseFind(UChar c, size_t start = UINT_MAX) const {
    return m_impl.rfind(c, start);
  }
  void swap(String16& other) {
    m_impl.swap(other.m_impl);
    std::swap(hash_code, other.hash_code);
  }

  // Convenience methods.
  V8_EXPORT std::string utf8() const;
  V8_EXPORT static String16 fromUTF8(const char* stringStart, size_t length);

  // Instantiates a String16 in native endianness from UTF16 LE.
  // On Big endian architectures, byte order needs to be flipped.
  V8_EXPORT static String16 fromUTF16LE(const UChar* stringStart,
                                        size_t length);

  std::size_t hash() const {
    if (!hash_code) {
      for (char c : m_impl) hash_code = 31 * hash_code + c;
      // Map hash code 0 to 1. This double the number of hash collisions for 1,
      // but avoids recomputing the hash code.
      if (!hash_code) ++hash_code;
    }
    return hash_code;
  }

  inline bool operator==(const String16& other) const {
    return m_impl == other.m_impl;
  }
  inline bool operator<(const String16& other) const {
    return m_impl < other.m_impl;
  }
  inline bool operator!=(const String16& other) const {
    return m_impl != other.m_impl;
  }
  inline String16 operator+(const String16& other) const {
    return String16(m_impl + other.m_impl);
  }
  inline String16& operator+=(const String16& other) {
    m_impl += other.m_impl;
    return *this;
  }

  // Defined later, since it uses the String16Builder.
  template <typename... T>
  static String16 concat(T... args);

 private:
  std::basic_string<UChar> m_impl;
  mutable std::size_t hash_code = 0;
};

inline String16 operator+(const char* a, const String16& b) {
  return String16(a) + b;
}

class String16Builder {
 public:
  String16Builder();
  void append(const String16&);
  void append(UChar);
  void append(char);
  void append(const UChar*, size_t);
  void append(const char*, size_t);
  void appendNumber(int);
  void appendNumber(size_t);
  void appendUnsignedAsHex(uint64_t);
  void appendUnsignedAsHex(uint32_t);
  void appendUnsignedAsHex(uint8_t);
  String16 toString();
  void reserveCapacity(size_t);

  template <typename T, typename... R>
  void appendAll(T first, R... rest) {
    append(first);
    appendAll(rest...);
  }
  void appendAll() {}

 private:
  std::vector<UChar> m_buffer;
};

template <typename... T>
String16 String16::concat(T... args) {
  String16Builder builder;
  builder.appendAll(args...);
  return builder.toString();
}

}  // namespace v8_inspector

#if !defined(__APPLE__) || defined(_LIBCPP_VERSION)

namespace std {
template <>
struct hash<v8_inspector::String16> {
  std::size_t operator()(const v8_inspector::String16& string) const {
    return string.hash();
  }
};

}  // namespace std

#endif  // !defined(__APPLE__) || defined(_LIBCPP_VERSION)

// See third_party/inspector_protocol/crdtp/serializer_traits.h.
namespace v8_crdtp {
template <>
struct SerializerTraits<v8_inspector::String16> {
  static void Serialize(const v8_inspector::String16& str,
                        std::vector<uint8_t>* out);
};
}  // namespace v8_crdtp

#endif  // V8_INSPECTOR_STRING_16_H_
