xref: /aosp_15_r20/external/deqp/framework/opengl/gluVarTypeUtil.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES Utilities
3  * ------------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Shader variable type utilities.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "gluVarTypeUtil.hpp"
25 
26 #include <stdlib.h>
27 
28 namespace glu
29 {
30 
31 // VarTokenizer
32 
VarTokenizer(const char * str)33 VarTokenizer::VarTokenizer(const char *str) : m_str(str), m_token(TOKEN_LAST), m_tokenStart(0), m_tokenLen(0)
34 {
35     advance();
36 }
37 
getNumber(void) const38 int VarTokenizer::getNumber(void) const
39 {
40     return atoi(getIdentifier().c_str());
41 }
42 
isNum(char c)43 static inline bool isNum(char c)
44 {
45     return de::inRange(c, '0', '9');
46 }
isAlpha(char c)47 static inline bool isAlpha(char c)
48 {
49     return de::inRange(c, 'a', 'z') || de::inRange(c, 'A', 'Z');
50 }
isIdentifierChar(char c)51 static inline bool isIdentifierChar(char c)
52 {
53     return isAlpha(c) || isNum(c) || c == '_';
54 }
55 
advance(void)56 void VarTokenizer::advance(void)
57 {
58     DE_ASSERT(m_token != TOKEN_END);
59 
60     m_tokenStart += m_tokenLen;
61     m_token    = TOKEN_LAST;
62     m_tokenLen = 1;
63 
64     if (m_str[m_tokenStart] == '[')
65         m_token = TOKEN_LEFT_BRACKET;
66     else if (m_str[m_tokenStart] == ']')
67         m_token = TOKEN_RIGHT_BRACKET;
68     else if (m_str[m_tokenStart] == 0)
69         m_token = TOKEN_END;
70     else if (m_str[m_tokenStart] == '.')
71         m_token = TOKEN_PERIOD;
72     else if (isNum(m_str[m_tokenStart]))
73     {
74         m_token = TOKEN_NUMBER;
75         while (isNum(m_str[m_tokenStart + m_tokenLen]))
76             m_tokenLen += 1;
77     }
78     else if (isIdentifierChar(m_str[m_tokenStart]))
79     {
80         m_token = TOKEN_IDENTIFIER;
81         while (isIdentifierChar(m_str[m_tokenStart + m_tokenLen]))
82             m_tokenLen += 1;
83     }
84     else
85         TCU_FAIL("Unexpected character");
86 }
87 
88 // SubTypeAccess
89 
SubTypeAccess(const VarType & type)90 SubTypeAccess::SubTypeAccess(const VarType &type) : m_type(type)
91 {
92 }
93 
parseVariableName(const char * nameWithPath)94 std::string parseVariableName(const char *nameWithPath)
95 {
96     VarTokenizer tokenizer(nameWithPath);
97     TCU_CHECK(tokenizer.getToken() == VarTokenizer::TOKEN_IDENTIFIER);
98     return tokenizer.getIdentifier();
99 }
100 
parseTypePath(const char * nameWithPath,const VarType & type,TypeComponentVector & path)101 void parseTypePath(const char *nameWithPath, const VarType &type, TypeComponentVector &path)
102 {
103     VarTokenizer tokenizer(nameWithPath);
104 
105     if (tokenizer.getToken() == VarTokenizer::TOKEN_IDENTIFIER)
106         tokenizer.advance();
107 
108     path.clear();
109     while (tokenizer.getToken() != VarTokenizer::TOKEN_END)
110     {
111         VarType curType = getVarType(type, path);
112 
113         if (tokenizer.getToken() == VarTokenizer::TOKEN_PERIOD)
114         {
115             tokenizer.advance();
116             TCU_CHECK(tokenizer.getToken() == VarTokenizer::TOKEN_IDENTIFIER);
117             TCU_CHECK_MSG(curType.isStructType(), "Invalid field selector");
118 
119             // Find member.
120             std::string memberName = tokenizer.getIdentifier();
121             int ndx                = 0;
122             for (; ndx < curType.getStructPtr()->getNumMembers(); ndx++)
123             {
124                 if (memberName == curType.getStructPtr()->getMember(ndx).getName())
125                     break;
126             }
127             TCU_CHECK_MSG(ndx < curType.getStructPtr()->getNumMembers(), "Member not found in type");
128 
129             path.push_back(VarTypeComponent(VarTypeComponent::STRUCT_MEMBER, ndx));
130             tokenizer.advance();
131         }
132         else if (tokenizer.getToken() == VarTokenizer::TOKEN_LEFT_BRACKET)
133         {
134             tokenizer.advance();
135             TCU_CHECK(tokenizer.getToken() == VarTokenizer::TOKEN_NUMBER);
136 
137             int ndx = tokenizer.getNumber();
138 
139             if (curType.isArrayType())
140             {
141                 TCU_CHECK(de::inBounds(ndx, 0, curType.getArraySize()));
142                 path.push_back(VarTypeComponent(VarTypeComponent::ARRAY_ELEMENT, ndx));
143             }
144             else if (curType.isBasicType() && isDataTypeMatrix(curType.getBasicType()))
145             {
146                 TCU_CHECK(de::inBounds(ndx, 0, getDataTypeMatrixNumColumns(curType.getBasicType())));
147                 path.push_back(VarTypeComponent(VarTypeComponent::MATRIX_COLUMN, ndx));
148             }
149             else if (curType.isBasicType() && isDataTypeVector(curType.getBasicType()))
150             {
151                 TCU_CHECK(de::inBounds(ndx, 0, getDataTypeScalarSize(curType.getBasicType())));
152                 path.push_back(VarTypeComponent(VarTypeComponent::VECTOR_COMPONENT, ndx));
153             }
154             else
155                 TCU_FAIL("Invalid subscript");
156 
157             tokenizer.advance();
158             TCU_CHECK(tokenizer.getToken() == VarTokenizer::TOKEN_RIGHT_BRACKET);
159             tokenizer.advance();
160         }
161         else
162             TCU_FAIL("Unexpected token");
163     }
164 }
165 
operator <<(std::ostream & str,const TypeAccessFormat & format)166 std::ostream &operator<<(std::ostream &str, const TypeAccessFormat &format)
167 {
168     const VarType *curType = &format.type;
169 
170     for (TypeComponentVector::const_iterator iter = format.path.begin(); iter != format.path.end(); iter++)
171     {
172         switch (iter->type)
173         {
174         case VarTypeComponent::ARRAY_ELEMENT:
175             curType = &curType->getElementType(); // Update current type.
176                                                   // Fall-through.
177 
178         case VarTypeComponent::MATRIX_COLUMN:
179         case VarTypeComponent::VECTOR_COMPONENT:
180             str << "[" << iter->index << "]";
181             break;
182 
183         case VarTypeComponent::STRUCT_MEMBER:
184         {
185             const StructMember &member = curType->getStructPtr()->getMember(iter->index);
186             str << "." << member.getName();
187             curType = &member.getType();
188             break;
189         }
190 
191         default:
192             DE_ASSERT(false);
193         }
194     }
195 
196     return str;
197 }
198 
199 } // namespace glu
200