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 "compiler/translator/ImmutableString.h"
14 
15 namespace sh
16 {
17 
18 class ImmutableStringBuilder
19 {
20   public:
ImmutableStringBuilder(size_t maxLength)21     ImmutableStringBuilder(size_t maxLength)
22         : mPos(0u), mMaxLength(maxLength), mData(AllocateEmptyPoolCharArray(maxLength))
23     {}
24 
25     ImmutableStringBuilder &operator<<(const ImmutableString &str);
26 
27     ImmutableStringBuilder &operator<<(const char *str);
28 
29     ImmutableStringBuilder &operator<<(const char &c);
30 
31     // This invalidates the ImmutableStringBuilder, so it should only be called once.
32     operator ImmutableString();
33 
34     void appendDecimal(const uint32_t &i);
35 
36     template <typename T>
appendHex(T number)37     void appendHex(T number)
38     {
39         ASSERT(mData != nullptr);
40         ASSERT(mPos + sizeof(T) * 2u <= mMaxLength);
41         int index = static_cast<int>(sizeof(T)) * 2 - 1;
42         // Loop through leading zeroes.
43         while (((number >> (index * 4)) & 0xfu) == 0 && index > 0)
44         {
45             --index;
46         }
47         // Write the rest of the hex digits.
48         while (index >= 0)
49         {
50             char digit     = static_cast<char>((number >> (index * 4)) & 0xfu);
51             char digitChar = (digit < 10) ? (digit + '0') : (digit + ('a' - 10));
52             mData[mPos++]  = digitChar;
53             --index;
54         }
55     }
56 
57     template <typename T>
GetHexCharCount()58     static constexpr size_t GetHexCharCount()
59     {
60         return sizeof(T) * 2;
61     }
62 
63   private:
AllocateEmptyPoolCharArray(size_t strLength)64     inline static char *AllocateEmptyPoolCharArray(size_t strLength)
65     {
66         size_t requiredSize = strLength + 1u;
67         return static_cast<char *>(GetGlobalPoolAllocator()->allocate(requiredSize));
68     }
69 
70     size_t mPos;
71     size_t mMaxLength;
72     char *mData;
73 };
74 
75 // GLSL ES 3.00.6 section 3.9: the maximum length of an identifier is 1024 characters.
76 constexpr unsigned int kESSLMaxIdentifierLength = 1024u;
77 
78 }  // namespace sh
79 
80 #endif  // COMPILER_TRANSLATOR_IMMUTABLESTRINGBUILDER_H_
81