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 // ImmutableStringBuilder.h: Stringstream-like utility for building pool allocated strings where the 7 // maximum length is known in advance. 8 // 9 10 #ifndef COMPILER_TRANSLATOR_IMMUTABLESTRINGBUILDER_H_ 11 #define COMPILER_TRANSLATOR_IMMUTABLESTRINGBUILDER_H_ 12 13 #include <cstring> 14 15 #include "compiler/translator/ImmutableString.h" 16 17 namespace sh 18 { 19 20 class ImmutableStringBuilder 21 { 22 public: ImmutableStringBuilder(size_t maxLength)23 ImmutableStringBuilder(size_t maxLength) 24 : mPos(0u), mMaxLength(maxLength), mData(AllocateEmptyPoolCharArray(maxLength)) 25 {} 26 27 ImmutableStringBuilder &operator<<(const ImmutableString &str); 28 ImmutableStringBuilder &operator<<(const char *str) { return *this << ImmutableString(str); } 29 ImmutableStringBuilder &operator<<(char c); 30 ImmutableStringBuilder &operator<<(int i) { return *this << static_cast<int64_t>(i); } 31 ImmutableStringBuilder &operator<<(unsigned i) { return *this << static_cast<uint64_t>(i); } 32 ImmutableStringBuilder &operator<<(int64_t i); 33 ImmutableStringBuilder &operator<<(uint64_t i); 34 35 // This invalidates the ImmutableStringBuilder, so it should only be called once. 36 operator ImmutableString(); 37 38 template <typename T> appendHex(T number)39 void appendHex(T number) 40 { 41 ASSERT(mData != nullptr); 42 ASSERT(mPos + sizeof(T) * 2u <= mMaxLength); 43 int index = static_cast<int>(sizeof(T)) * 2 - 1; 44 // Loop through leading zeroes. 45 while (((number >> (index * 4)) & 0xfu) == 0 && index > 0) 46 { 47 --index; 48 } 49 // Write the rest of the hex digits. 50 while (index >= 0) 51 { 52 char digit = static_cast<char>((number >> (index * 4)) & 0xfu); 53 char digitChar = (digit < 10) ? (digit + '0') : (digit + ('a' - 10)); 54 mData[mPos++] = digitChar; 55 --index; 56 } 57 } 58 59 template <typename T> GetHexCharCount()60 static constexpr size_t GetHexCharCount() 61 { 62 return sizeof(T) * 2; 63 } 64 65 private: AllocateEmptyPoolCharArray(size_t strLength)66 inline static char *AllocateEmptyPoolCharArray(size_t strLength) 67 { 68 size_t requiredSize = strLength + 1u; 69 return static_cast<char *>(GetGlobalPoolAllocator()->allocate(requiredSize)); 70 } 71 72 size_t mPos; 73 size_t mMaxLength; 74 char *mData; 75 }; 76 77 // GLSL ES 3.00.6 section 3.9: the maximum length of an identifier is 1024 characters. 78 constexpr unsigned int kESSLMaxIdentifierLength = 1024u; 79 80 namespace impl 81 { 82 GetCharCount(uint64_t x)83constexpr inline size_t GetCharCount(uint64_t x) 84 { 85 size_t digits = 1; 86 uint64_t max = 10; 87 for (; digits < 19; ++digits) 88 { 89 if (x < max) 90 break; 91 max *= 10; 92 } 93 return digits; 94 } 95 GetCharCount(int64_t x)96constexpr inline size_t GetCharCount(int64_t x) 97 { 98 if (x == INT64_MIN) 99 { 100 return 19 + 1; 101 } 102 if (x < 0) 103 { 104 return GetCharCount(static_cast<uint64_t>(-x)) + 1; 105 } 106 return GetCharCount(static_cast<uint64_t>(x)); 107 } 108 GetCharCount(int x)109constexpr inline size_t GetCharCount(int x) 110 { 111 return GetCharCount(static_cast<int64_t>(x)); 112 } 113 GetCharCount(unsigned x)114constexpr inline size_t GetCharCount(unsigned x) 115 { 116 return GetCharCount(static_cast<int64_t>(x)); 117 } 118 GetCharCount(const ImmutableString & str)119constexpr inline size_t GetCharCount(const ImmutableString &str) 120 { 121 return str.length(); 122 } 123 GetCharCount(const char * str)124constexpr inline size_t GetCharCount(const char *str) 125 { 126 return angle::ConstStrLen(str); 127 } 128 GetCharCount(char)129constexpr inline size_t GetCharCount(char) 130 { 131 return 1; 132 } 133 134 } // namespace impl 135 136 template <typename... Args> BuildConcatenatedImmutableString(Args...args)137ImmutableString BuildConcatenatedImmutableString(Args... args) 138 { 139 ImmutableStringBuilder builder((impl::GetCharCount(args) + ...)); 140 (builder << ... << args); 141 return builder; 142 } 143 144 } // namespace sh 145 146 #endif // COMPILER_TRANSLATOR_IMMUTABLESTRINGBUILDER_H_ 147