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