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