1//
2// Copyright (c) 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
18namespace sh
19{
20
21namespace
22{
23constexpr 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
38class 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.
46 explicit constexpr ImmutableString(const char *data) : mData(data), mLength(constStrlen(data))
47 {}
48
49 constexpr ImmutableString(const char *data, size_t length) : mData(data), mLength(length) {}
50
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
59 constexpr const char *data() const { return mData ? mData : ""; }
60 constexpr size_t length() const { return mLength; }
61
62 char operator[](size_t index) const { return data()[index]; }
63
64 constexpr bool empty() const { return mLength == 0; }
65 bool beginsWith(const char *prefix) const { return angle::BeginsWith(data(), prefix); }
66 constexpr bool beginsWith(const ImmutableString &prefix) const
67 {
68 return mLength >= prefix.length() && memcmp(data(), prefix.data(), prefix.length()) == 0;
69 }
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
115 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 // This hash encodes the opening parentheses location (if any), name length and whether the name
130 // contains { or [ characters in addition to a 19-bit hash. This way the hash is more useful for
131 // lookups. The string passed in should be at most 63 characters.
132 uint32_t mangledNameHash() const;
133
134 private:
135 const char *mData;
136 size_t mLength;
137};
138
139constexpr ImmutableString kEmptyImmutableString("");
140} // namespace sh
141
142std::ostream &operator<<(std::ostream &os, const sh::ImmutableString &str);
143
144#endif // COMPILER_TRANSLATOR_IMMUTABLESTRING_H_
145