blob: 2caef8de8d7c8d0e92b9b13cef70c0a97a8eafcb [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 Etuaho2d8e4322018-01-22 14:12:46 +020057 ImmutableString(const ImmutableString &) = default;
58 ImmutableString &operator=(const ImmutableString &) = default;
59
Olli Etuahofbb1c792018-01-19 16:26:59 +020060 constexpr const char *data() const { return mData ? mData : ""; }
61 constexpr size_t length() const { return mLength; }
Olli Etuaho2d8e4322018-01-22 14:12:46 +020062
Olli Etuahofbb1c792018-01-19 16:26:59 +020063 char operator[](size_t index) const { return data()[index]; }
64
65 constexpr bool empty() const { return mLength == 0; }
66 bool beginsWith(const char *prefix) const { return angle::BeginsWith(data(), prefix); }
67 constexpr bool beginsWith(const ImmutableString &prefix) const
68 {
69 return mLength >= prefix.length() && memcmp(data(), prefix.data(), prefix.length()) == 0;
70 }
71 bool contains(const char *substr) const { return strstr(data(), substr) != nullptr; }
72
73 constexpr bool operator==(const ImmutableString &b) const
74 {
75 if (mLength != b.mLength)
76 {
77 return false;
78 }
79 return memcmp(data(), b.data(), mLength) == 0;
80 }
81 constexpr bool operator!=(const ImmutableString &b) const { return !(*this == b); }
82 constexpr bool operator==(const char *b) const
83 {
84 if (b == nullptr)
85 {
86 return empty();
87 }
88 return strcmp(data(), b) == 0;
89 }
90 constexpr bool operator!=(const char *b) const { return !(*this == b); }
91 bool operator==(const std::string &b) const
92 {
93 return mLength == b.length() && memcmp(data(), b.c_str(), mLength) == 0;
94 }
95 bool operator!=(const std::string &b) const { return !(*this == b); }
96
97 constexpr bool operator<(const ImmutableString &b) const
Olli Etuaho2d8e4322018-01-22 14:12:46 +020098 {
99 if (mLength < b.mLength)
100 {
101 return true;
102 }
103 if (mLength > b.mLength)
104 {
105 return false;
106 }
107 return (memcmp(data(), b.data(), mLength) < 0);
108 }
109
Olli Etuahofbb1c792018-01-19 16:26:59 +0200110 template <size_t hashBytes>
111 struct FowlerNollVoHash
112 {
113 static const size_t kFnvOffsetBasis;
114 static const size_t kFnvPrime;
115
116 constexpr size_t operator()(const ImmutableString &a) const
117 {
118 const char *data = a.data();
119 size_t hash = kFnvOffsetBasis;
120 while ((*data) != '\0')
121 {
122 hash = hash ^ (*data);
123 hash = hash * kFnvPrime;
124 ++data;
125 }
126 return hash;
127 }
128 };
129
Olli Etuaho2d8e4322018-01-22 14:12:46 +0200130 private:
Olli Etuaho12c03762018-01-25 12:22:33 +0200131 const char *mData;
132 size_t mLength;
Olli Etuaho2d8e4322018-01-22 14:12:46 +0200133};
134
135} // namespace sh
136
Olli Etuaho12c03762018-01-25 12:22:33 +0200137std::ostream &operator<<(std::ostream &os, const sh::ImmutableString &str);
138
Olli Etuaho2d8e4322018-01-22 14:12:46 +0200139#endif // COMPILER_TRANSLATOR_IMMUTABLESTRING_H_