OLD | NEW |
---|---|
1 // Copyright 2016 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_INSPECTOR_STRING16_H_ | 5 #ifndef V8_INSPECTOR_STRING16_H_ |
6 #define V8_INSPECTOR_STRING16_H_ | 6 #define V8_INSPECTOR_STRING16_H_ |
7 | 7 |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 #include <cctype> | 9 #include <cctype> |
10 #include <climits> | 10 #include <climits> |
11 #include <cstring> | 11 #include <cstring> |
12 #include <string> | 12 #include <string> |
13 #include <vector> | 13 #include <vector> |
14 | 14 |
15 namespace v8_inspector { | 15 namespace v8_inspector { |
16 | 16 |
17 using UChar = uint16_t; | 17 using UChar = uint16_t; |
18 | 18 |
19 class String16 { | 19 class String16 { |
20 public: | 20 public: |
21 static const size_t kNotFound = static_cast<size_t>(-1); | 21 static const size_t kNotFound = static_cast<size_t>(-1); |
22 | 22 |
23 String16() {} | 23 String16() {} |
24 String16(const String16& other) : m_impl(other.m_impl) {} | 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) {} | |
25 String16(const UChar* characters, size_t size) : m_impl(characters, size) {} | 28 String16(const UChar* characters, size_t size) : m_impl(characters, size) {} |
26 String16(const UChar* characters) // NOLINT(runtime/explicit) | 29 String16(const UChar* characters) // NOLINT(runtime/explicit) |
27 : m_impl(characters) {} | 30 : m_impl(characters) {} |
28 String16(const char* characters) // NOLINT(runtime/explicit) | 31 String16(const char* characters) // NOLINT(runtime/explicit) |
29 : String16(characters, std::strlen(characters)) {} | 32 : String16(characters, std::strlen(characters)) {} |
30 String16(const char* characters, size_t size) { | 33 String16(const char* characters, size_t size) { |
31 m_impl.resize(size); | 34 m_impl.resize(size); |
32 for (size_t i = 0; i < size; ++i) m_impl[i] = characters[i]; | 35 for (size_t i = 0; i < size; ++i) m_impl[i] = characters[i]; |
33 } | 36 } |
37 explicit String16(const std::basic_string<UChar>& impl) : m_impl(impl) {} | |
38 | |
39 String16& operator=(const String16& other) = default; | |
dgozman
2016/11/11 21:41:21
Let's have operator=(const String16&&) as well?
Clemens Hammacher
2016/11/14 06:02:07
Sure, I will add it when rebasing.
| |
34 | 40 |
35 static String16 fromInteger(int); | 41 static String16 fromInteger(int); |
36 static String16 fromInteger(size_t); | 42 static String16 fromInteger(size_t); |
37 static String16 fromDouble(double); | 43 static String16 fromDouble(double); |
38 static String16 fromDouble(double, int precision); | 44 static String16 fromDouble(double, int precision); |
39 | 45 |
40 int toInteger(bool* ok = nullptr) const; | 46 int toInteger(bool* ok = nullptr) const; |
41 String16 stripWhiteSpace() const; | 47 String16 stripWhiteSpace() const; |
42 const UChar* characters16() const { return m_impl.c_str(); } | 48 const UChar* characters16() const { return m_impl.c_str(); } |
43 size_t length() const { return m_impl.length(); } | 49 size_t length() const { return m_impl.length(); } |
44 bool isEmpty() const { return !m_impl.length(); } | 50 bool isEmpty() const { return !m_impl.length(); } |
45 UChar operator[](size_t index) const { return m_impl[index]; } | 51 UChar operator[](size_t index) const { return m_impl[index]; } |
46 String16 substring(size_t pos, size_t len = UINT_MAX) const { | 52 String16 substring(size_t pos, size_t len = UINT_MAX) const { |
47 return String16(m_impl.substr(pos, len)); | 53 return String16(m_impl.substr(pos, len)); |
48 } | 54 } |
49 size_t find(const String16& str, size_t start = 0) const { | 55 size_t find(const String16& str, size_t start = 0) const { |
50 return m_impl.find(str.m_impl, start); | 56 return m_impl.find(str.m_impl, start); |
51 } | 57 } |
52 size_t reverseFind(const String16& str, size_t start = UINT_MAX) const { | 58 size_t reverseFind(const String16& str, size_t start = UINT_MAX) const { |
53 return m_impl.rfind(str.m_impl, start); | 59 return m_impl.rfind(str.m_impl, start); |
54 } | 60 } |
55 void swap(String16& other) { m_impl.swap(other.m_impl); } | 61 size_t find(UChar c, size_t start = 0) const { return m_impl.find(c, start); } |
62 size_t reverseFind(UChar c, size_t start = UINT_MAX) const { | |
63 return m_impl.rfind(c, start); | |
64 } | |
65 void swap(String16& other) { | |
66 m_impl.swap(other.m_impl); | |
67 std::swap(hash_code, other.hash_code); | |
68 } | |
56 | 69 |
57 // Convenience methods. | 70 // Convenience methods. |
58 std::string utf8() const; | 71 std::string utf8() const; |
59 static String16 fromUTF8(const char* stringStart, size_t length); | 72 static String16 fromUTF8(const char* stringStart, size_t length); |
60 | 73 |
61 const std::basic_string<UChar>& impl() const { return m_impl; } | |
62 explicit String16(const std::basic_string<UChar>& impl) : m_impl(impl) {} | |
63 | |
64 std::size_t hash() const { | 74 std::size_t hash() const { |
65 if (!has_hash) { | 75 if (!hash_code) { |
66 size_t hash = 0; | 76 for (char c : m_impl) hash_code = 31 * hash_code + c; |
67 for (size_t i = 0; i < length(); ++i) hash = 31 * hash + m_impl[i]; | 77 // Map hash code 0 to 1. This double the number of hash collisions for 1, |
68 hash_code = hash; | 78 // but avoids recomputing the hash code. |
69 has_hash = true; | 79 if (!hash_code) ++hash_code; |
dgozman
2016/11/11 21:41:21
What if hash_code == -1?
Clemens Hammacher
2016/11/14 06:02:07
Then !hash_code will be false, so it stays -1.
dgozman
2016/11/14 20:32:52
Ops, my bad :-)
| |
70 } | 80 } |
71 return hash_code; | 81 return hash_code; |
72 } | 82 } |
73 | 83 |
84 inline bool operator==(const String16& other) const { | |
85 return m_impl == other.m_impl; | |
86 } | |
87 inline bool operator<(const String16& other) const { | |
88 return m_impl < other.m_impl; | |
89 } | |
90 inline bool operator!=(const String16& other) const { | |
91 return m_impl != other.m_impl; | |
92 } | |
93 inline String16 operator+(const String16& other) const { | |
94 return String16(m_impl + other.m_impl); | |
95 } | |
96 | |
97 // Defined later, since it uses the String16Builder. | |
98 template <typename... T> | |
99 static String16 concat(T... args); | |
100 | |
74 private: | 101 private: |
75 std::basic_string<UChar> m_impl; | 102 std::basic_string<UChar> m_impl; |
76 mutable bool has_hash = false; | |
77 mutable std::size_t hash_code = 0; | 103 mutable std::size_t hash_code = 0; |
78 }; | 104 }; |
79 | 105 |
80 inline bool operator==(const String16& a, const String16& b) { | |
81 return a.impl() == b.impl(); | |
82 } | |
83 inline bool operator<(const String16& a, const String16& b) { | |
84 return a.impl() < b.impl(); | |
85 } | |
86 inline bool operator!=(const String16& a, const String16& b) { | |
87 return a.impl() != b.impl(); | |
88 } | |
89 inline bool operator==(const String16& a, const char* b) { | |
90 return a.impl() == String16(b).impl(); | |
91 } | |
92 inline String16 operator+(const String16& a, const char* b) { | |
dgozman
2016/11/11 21:41:21
Where did this one go?
Clemens Hammacher
2016/11/14 06:02:07
It's redundant, since there is a String16(const ch
| |
93 return String16(a.impl() + String16(b).impl()); | |
94 } | |
95 inline String16 operator+(const char* a, const String16& b) { | 106 inline String16 operator+(const char* a, const String16& b) { |
96 return String16(String16(a).impl() + b.impl()); | 107 return String16(a) + b; |
97 } | |
98 inline String16 operator+(const String16& a, const String16& b) { | |
99 return String16(a.impl() + b.impl()); | |
100 } | 108 } |
101 | 109 |
102 class String16Builder { | 110 class String16Builder { |
103 public: | 111 public: |
104 String16Builder(); | 112 String16Builder(); |
105 void append(const String16&); | 113 void append(const String16&); |
106 void append(UChar); | 114 void append(UChar); |
107 void append(char); | 115 void append(char); |
108 void append(const UChar*, size_t); | 116 void append(const UChar*, size_t); |
109 void append(const char*, size_t); | 117 void append(const char*, size_t); |
118 void append(int); | |
dgozman
2016/11/11 21:41:21
I think these are error-prone, since the semantic
Clemens Hammacher
2016/11/14 06:02:08
I see the problem. Renaming the functions would ma
dgozman
2016/11/14 20:32:52
Maybe don't support integer than? Why not pass Str
Clemens Hammacher
2016/11/14 21:11:02
Hm, that degrades performance and readability, whi
| |
119 void append(size_t); | |
110 String16 toString(); | 120 String16 toString(); |
111 void reserveCapacity(size_t); | 121 void reserveCapacity(size_t); |
112 | 122 |
123 template <typename T, typename... R> | |
124 void appendAll(T first, R... rest) { | |
125 append(first); | |
126 appendAll(rest...); | |
127 } | |
128 void appendAll() {} | |
129 | |
113 private: | 130 private: |
114 std::vector<UChar> m_buffer; | 131 std::vector<UChar> m_buffer; |
115 }; | 132 }; |
116 | 133 |
134 template <typename... T> | |
135 String16 String16::concat(T... args) { | |
136 String16Builder builder; | |
137 builder.appendAll(args...); | |
138 return builder.toString(); | |
139 } | |
140 | |
117 } // namespace v8_inspector | 141 } // namespace v8_inspector |
118 | 142 |
119 #if !defined(__APPLE__) || defined(_LIBCPP_VERSION) | 143 #if !defined(__APPLE__) || defined(_LIBCPP_VERSION) |
120 | 144 |
121 namespace std { | 145 namespace std { |
122 template <> | 146 template <> |
123 struct hash<v8_inspector::String16> { | 147 struct hash<v8_inspector::String16> { |
124 std::size_t operator()(const v8_inspector::String16& string) const { | 148 std::size_t operator()(const v8_inspector::String16& string) const { |
125 return string.hash(); | 149 return string.hash(); |
126 } | 150 } |
127 }; | 151 }; |
128 | 152 |
129 } // namespace std | 153 } // namespace std |
130 | 154 |
131 #endif // !defined(__APPLE__) || defined(_LIBCPP_VERSION) | 155 #endif // !defined(__APPLE__) || defined(_LIBCPP_VERSION) |
132 | 156 |
133 #endif // V8_INSPECTOR_STRING16_H_ | 157 #endif // V8_INSPECTOR_STRING16_H_ |
OLD | NEW |