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