1 //
2 // Copyright 2018 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // ImmutableString.h: Wrapper for static or pool allocated char arrays, that are guaranteed to be
7 // valid and unchanged for the duration of the compilation.
8 //
9
10 #ifndef COMPILER_TRANSLATOR_IMMUTABLESTRING_H_
11 #define COMPILER_TRANSLATOR_IMMUTABLESTRING_H_
12
13 #include <string>
14
15 #include "common/string_utils.h"
16 #include "compiler/translator/Common.h"
17
18 namespace sh
19 {
20
21 namespace
22 {
constStrlen(const char * str)23 constexpr size_t constStrlen(const char *str)
24 {
25 if (str == nullptr)
26 {
27 return 0u;
28 }
29 size_t len = 0u;
30 while (*(str + len) != '\0')
31 {
32 ++len;
33 }
34 return len;
35 }
36 } // namespace
37
38 class ImmutableString
39 {
40 public:
41 // The data pointer passed in must be one of:
42 // 1. nullptr (only valid with length 0).
43 // 2. a null-terminated static char array like a string literal.
44 // 3. a null-terminated pool allocated char array. This can't be c_str() of a local TString,
45 // since when a TString goes out of scope it clears its first character.
ImmutableString(const char * data)46 explicit constexpr ImmutableString(const char *data) : mData(data), mLength(constStrlen(data))
47 {}
48
ImmutableString(const char * data,size_t length)49 constexpr ImmutableString(const char *data, size_t length) : mData(data), mLength(length) {}
50
ImmutableString(const std::string & str)51 ImmutableString(const std::string &str)
52 : mData(AllocatePoolCharArray(str.c_str(), str.size())), mLength(str.size())
53 {}
54
55 constexpr ImmutableString(const ImmutableString &) = default;
56
57 ImmutableString &operator=(const ImmutableString &) = default;
58
data()59 constexpr const char *data() const { return mData ? mData : ""; }
length()60 constexpr size_t length() const { return mLength; }
61
62 char operator[](size_t index) const { return data()[index]; }
63
empty()64 constexpr bool empty() const { return mLength == 0; }
beginsWith(const char * prefix)65 bool beginsWith(const char *prefix) const { return angle::BeginsWith(data(), prefix); }
beginsWith(const ImmutableString & prefix)66 constexpr bool beginsWith(const ImmutableString &prefix) const
67 {
68 return mLength >= prefix.length() && memcmp(data(), prefix.data(), prefix.length()) == 0;
69 }
contains(const char * substr)70 bool contains(const char *substr) const { return strstr(data(), substr) != nullptr; }
71
72 constexpr bool operator==(const ImmutableString &b) const
73 {
74 if (mLength != b.mLength)
75 {
76 return false;
77 }
78 return memcmp(data(), b.data(), mLength) == 0;
79 }
80 constexpr bool operator!=(const ImmutableString &b) const { return !(*this == b); }
81 constexpr bool operator==(const char *b) const
82 {
83 if (b == nullptr)
84 {
85 return empty();
86 }
87 return strcmp(data(), b) == 0;
88 }
89 constexpr bool operator!=(const char *b) const { return !(*this == b); }
90 bool operator==(const std::string &b) const
91 {
92 return mLength == b.length() && memcmp(data(), b.c_str(), mLength) == 0;
93 }
94 bool operator!=(const std::string &b) const { return !(*this == b); }
95
96 constexpr bool operator<(const ImmutableString &b) const
97 {
98 if (mLength < b.mLength)
99 {
100 return true;
101 }
102 if (mLength > b.mLength)
103 {
104 return false;
105 }
106 return (memcmp(data(), b.data(), mLength) < 0);
107 }
108
109 template <size_t hashBytes>
110 struct FowlerNollVoHash
111 {
112 static const size_t kFnvOffsetBasis;
113 static const size_t kFnvPrime;
114
operatorFowlerNollVoHash115 constexpr size_t operator()(const ImmutableString &a) const
116 {
117 const char *data = a.data();
118 size_t hash = kFnvOffsetBasis;
119 while ((*data) != '\0')
120 {
121 hash = hash ^ (*data);
122 hash = hash * kFnvPrime;
123 ++data;
124 }
125 return hash;
126 }
127 };
128
129 // Perfect hash functions
130 uint32_t mangledNameHash() const;
131 uint32_t unmangledNameHash() const;
132
133 private:
134 const char *mData;
135 size_t mLength;
136 };
137
138 constexpr ImmutableString kEmptyImmutableString("");
139 } // namespace sh
140
141 std::ostream &operator<<(std::ostream &os, const sh::ImmutableString &str);
142
143 #endif // COMPILER_TRANSLATOR_IMMUTABLESTRING_H_
144