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