// 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 fromDouble(double);
  static String16 fromDouble(double, int precision);

  int64_t toInteger64(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);
  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_
