blob: a9e167330847fbddba3b801766610d66e633d3d7 [file] [log] [blame]
Olli Etuaho2d8e4322018-01-22 14:12:46 +02001//
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
Olli Etuahofbb1c792018-01-19 16:26:59 +020015#include "common/string_utils.h"
Olli Etuaho2d8e4322018-01-22 14:12:46 +020016#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}
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.
Olli Etuahofbb1c792018-01-19 16:26:59 +020044 // 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.
Olli Etuaho2d8e4322018-01-22 14:12:46 +020046 explicit constexpr ImmutableString(const char *data) : mData(data), mLength(constStrlen(data))
47 {
48 }
49
Olli Etuaho12c03762018-01-25 12:22:33 +020050 constexpr ImmutableString(const char *data, size_t length) : mData(data), mLength(length) {}
51
Olli Etuahofbb1c792018-01-19 16:26:59 +020052 ImmutableString(const std::string &str)
53 : mData(AllocatePoolCharArray(str.c_str(), str.size())), mLength(str.size())
54 {
55 }
56
Olli Etuaho7b17fa12018-01-29 11:12:57 +020057 constexpr ImmutableString(const ImmutableString &) = default;
58
Olli Etuaho2d8e4322018-01-22 14:12:46 +020059 ImmutableString &operator=(const ImmutableString &) = default;
60
Olli Etuahofbb1c792018-01-19 16:26:59 +020061 constexpr const char *data() const { return mData ? mData : ""; }
62 constexpr size_t length() const { return mLength; }
Olli Etuaho2d8e4322018-01-22 14:12:46 +020063
Olli Etuahofbb1c792018-01-19 16:26:59 +020064 char operator[](size_t index) const { return data()[index]; }
65
66 constexpr bool empty() const { return mLength == 0; }
67 bool beginsWith(const char *prefix) const { return angle::BeginsWith(data(), prefix); }
68 constexpr bool beginsWith(const ImmutableString &prefix) const
69 {
70 return mLength >= prefix.length() && memcmp(data(), prefix.data(), prefix.length()) == 0;
71 }
72 bool contains(const char *substr) const { return strstr(data(), substr) != nullptr; }
73
74 constexpr bool operator==(const ImmutableString &b) const
75 {
76 if (mLength != b.mLength)
77 {
78 return false;
79 }
80 return memcmp(data(), b.data(), mLength) == 0;
81 }
82 constexpr bool operator!=(const ImmutableString &b) const { return !(*this == b); }
83 constexpr bool operator==(const char *b) const
84 {
85 if (b == nullptr)
86 {
87 return empty();
88 }
89 return strcmp(data(), b) == 0;
90 }
91 constexpr bool operator!=(const char *b) const { return !(*this == b); }
92 bool operator==(const std::string &b) const
93 {
94 return mLength == b.length() && memcmp(data(), b.c_str(), mLength) == 0;
95 }
96 bool operator!=(const std::string &b) const { return !(*this == b); }
97
98 constexpr bool operator<(const ImmutableString &b) const
Olli Etuaho2d8e4322018-01-22 14:12:46 +020099 {
100 if (mLength < b.mLength)
101 {
102 return true;
103 }
104 if (mLength > b.mLength)
105 {
106 return false;
107 }
108 return (memcmp(data(), b.data(), mLength) < 0);
109 }
110
Olli Etuahofbb1c792018-01-19 16:26:59 +0200111 template <size_t hashBytes>
112 struct FowlerNollVoHash
113 {
114 static const size_t kFnvOffsetBasis;
115 static const size_t kFnvPrime;
116
117 constexpr size_t operator()(const ImmutableString &a) const
118 {
119 const char *data = a.data();
120 size_t hash = kFnvOffsetBasis;
121 while ((*data) != '\0')
122 {
123 hash = hash ^ (*data);
124 hash = hash * kFnvPrime;
125 ++data;
126 }
127 return hash;
128 }
129 };
130
Olli Etuaho3b678742018-03-21 12:59:19 +0200131 // This hash encodes the opening parentheses location (if any) and name length in addition to a
132 // 20-bit hash. This way the hash is more useful for lookups. The string passed in should be at
133 // most 63 characters.
134 uint32_t mangledNameHash() const;
Olli Etuahoc4bd0ac2018-02-22 16:29:32 +0200135
Olli Etuaho2d8e4322018-01-22 14:12:46 +0200136 private:
Olli Etuaho12c03762018-01-25 12:22:33 +0200137 const char *mData;
138 size_t mLength;
Olli Etuaho2d8e4322018-01-22 14:12:46 +0200139};
140
141} // namespace sh
142
Olli Etuaho12c03762018-01-25 12:22:33 +0200143std::ostream &operator<<(std::ostream &os, const sh::ImmutableString &str);
144
Olli Etuaho2d8e4322018-01-22 14:12:46 +0200145#endif // COMPILER_TRANSLATOR_IMMUTABLESTRING_H_