1f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// Copyright 2016 the V8 project authors. All rights reserved.
2f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// found in the LICENSE file.
4f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
5f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#ifndef V8_INSPECTOR_STRING16_H_
6f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#define V8_INSPECTOR_STRING16_H_
7f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
8f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include <stdint.h>
9f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include <cctype>
10f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include <climits>
11f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include <cstring>
12f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include <string>
13f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include <vector>
14f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
15f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochnamespace v8_inspector {
16f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
17f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochusing UChar = uint16_t;
18f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
19f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochclass String16 {
20f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch public:
21f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  static const size_t kNotFound = static_cast<size_t>(-1);
22f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
23f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  String16() {}
24c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  String16(const String16& other)
25c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      : m_impl(other.m_impl), hash_code(other.hash_code) {}
26c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  String16(const String16&& other)
27c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      : m_impl(std::move(other.m_impl)), hash_code(other.hash_code) {}
28f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  String16(const UChar* characters, size_t size) : m_impl(characters, size) {}
29f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  String16(const UChar* characters)  // NOLINT(runtime/explicit)
30f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      : m_impl(characters) {}
31f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  String16(const char* characters)  // NOLINT(runtime/explicit)
32f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      : String16(characters, std::strlen(characters)) {}
33f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  String16(const char* characters, size_t size) {
34f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    m_impl.resize(size);
35f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    for (size_t i = 0; i < size; ++i) m_impl[i] = characters[i];
36f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
37c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  explicit String16(const std::basic_string<UChar>& impl) : m_impl(impl) {}
38c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
39c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  String16& operator=(const String16& other) {
40c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    m_impl = other.m_impl;
41c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    hash_code = other.hash_code;
42c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return *this;
43c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
44c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  String16& operator=(String16&& other) {
45c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    m_impl = std::move(other.m_impl);
46c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    hash_code = other.hash_code;
47c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return *this;
48c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
49f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
50f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  static String16 fromInteger(int);
51f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  static String16 fromInteger(size_t);
52f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  static String16 fromDouble(double);
53f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  static String16 fromDouble(double, int precision);
54f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
55f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  int toInteger(bool* ok = nullptr) const;
56f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  String16 stripWhiteSpace() const;
57f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  const UChar* characters16() const { return m_impl.c_str(); }
58f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  size_t length() const { return m_impl.length(); }
59f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  bool isEmpty() const { return !m_impl.length(); }
60f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  UChar operator[](size_t index) const { return m_impl[index]; }
61f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  String16 substring(size_t pos, size_t len = UINT_MAX) const {
62f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    return String16(m_impl.substr(pos, len));
63f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
64f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  size_t find(const String16& str, size_t start = 0) const {
65f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    return m_impl.find(str.m_impl, start);
66f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
67f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  size_t reverseFind(const String16& str, size_t start = UINT_MAX) const {
68f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    return m_impl.rfind(str.m_impl, start);
69f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
70c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t find(UChar c, size_t start = 0) const { return m_impl.find(c, start); }
71c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t reverseFind(UChar c, size_t start = UINT_MAX) const {
72c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return m_impl.rfind(c, start);
73c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
74c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  void swap(String16& other) {
75c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    m_impl.swap(other.m_impl);
76c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    std::swap(hash_code, other.hash_code);
77c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
78f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
79f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Convenience methods.
80f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  std::string utf8() const;
81f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  static String16 fromUTF8(const char* stringStart, size_t length);
82f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
83f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  std::size_t hash() const {
84c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    if (!hash_code) {
85c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      for (char c : m_impl) hash_code = 31 * hash_code + c;
86c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      // Map hash code 0 to 1. This double the number of hash collisions for 1,
87c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      // but avoids recomputing the hash code.
88c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      if (!hash_code) ++hash_code;
89f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
90f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    return hash_code;
91f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
92f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
93c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  inline bool operator==(const String16& other) const {
94c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return m_impl == other.m_impl;
95c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
96c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  inline bool operator<(const String16& other) const {
97c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return m_impl < other.m_impl;
98c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
99c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  inline bool operator!=(const String16& other) const {
100c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return m_impl != other.m_impl;
101c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
102c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  inline String16 operator+(const String16& other) const {
103c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return String16(m_impl + other.m_impl);
104c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
105c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
106c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // Defined later, since it uses the String16Builder.
107c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  template <typename... T>
108c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  static String16 concat(T... args);
109c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
110f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch private:
111f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  std::basic_string<UChar> m_impl;
112f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  mutable std::size_t hash_code = 0;
113f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch};
114f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
115f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochinline String16 operator+(const char* a, const String16& b) {
116c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  return String16(a) + b;
117f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
118f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
119f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochclass String16Builder {
120f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch public:
121f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  String16Builder();
122f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void append(const String16&);
123f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void append(UChar);
124f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void append(char);
125f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void append(const UChar*, size_t);
126f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void append(const char*, size_t);
127c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  void appendNumber(int);
128c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  void appendNumber(size_t);
129f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  String16 toString();
130f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void reserveCapacity(size_t);
131f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
132c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  template <typename T, typename... R>
133c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  void appendAll(T first, R... rest) {
134c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    append(first);
135c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    appendAll(rest...);
136c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
137c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  void appendAll() {}
138c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
139f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch private:
140f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  std::vector<UChar> m_buffer;
141f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch};
142f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
143c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochtemplate <typename... T>
144c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochString16 String16::concat(T... args) {
145c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  String16Builder builder;
146c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  builder.appendAll(args...);
147c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  return builder.toString();
148c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
149c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
150f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}  // namespace v8_inspector
151f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
152f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#if !defined(__APPLE__) || defined(_LIBCPP_VERSION)
153f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
154f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochnamespace std {
155f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochtemplate <>
156f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochstruct hash<v8_inspector::String16> {
157f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  std::size_t operator()(const v8_inspector::String16& string) const {
158f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    return string.hash();
159f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
160f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch};
161f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
162f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}  // namespace std
163f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
164f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#endif  // !defined(__APPLE__) || defined(_LIBCPP_VERSION)
165f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
166f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#endif  // V8_INSPECTOR_STRING16_H_
167