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)
34 : m_str (str)
35 , m_token (TOKEN_LAST)
36 , m_tokenStart (0)
37 , m_tokenLen (0)
38 {
39 advance();
40 }
41
getNumber(void) const42 int VarTokenizer::getNumber (void) const
43 {
44 return atoi(getIdentifier().c_str());
45 }
46
isNum(char c)47 static inline bool isNum (char c) { return de::inRange(c, '0', '9'); }
isAlpha(char c)48 static inline bool isAlpha (char c) { return de::inRange(c, 'a', 'z') || de::inRange(c, 'A', 'Z'); }
isIdentifierChar(char c)49 static inline bool isIdentifierChar (char c) { return isAlpha(c) || isNum(c) || c == '_'; }
50
advance(void)51 void VarTokenizer::advance (void)
52 {
53 DE_ASSERT(m_token != TOKEN_END);
54
55 m_tokenStart += m_tokenLen;
56 m_token = TOKEN_LAST;
57 m_tokenLen = 1;
58
59 if (m_str[m_tokenStart] == '[')
60 m_token = TOKEN_LEFT_BRACKET;
61 else if (m_str[m_tokenStart] == ']')
62 m_token = TOKEN_RIGHT_BRACKET;
63 else if (m_str[m_tokenStart] == 0)
64 m_token = TOKEN_END;
65 else if (m_str[m_tokenStart] == '.')
66 m_token = TOKEN_PERIOD;
67 else if (isNum(m_str[m_tokenStart]))
68 {
69 m_token = TOKEN_NUMBER;
70 while (isNum(m_str[m_tokenStart+m_tokenLen]))
71 m_tokenLen += 1;
72 }
73 else if (isIdentifierChar(m_str[m_tokenStart]))
74 {
75 m_token = TOKEN_IDENTIFIER;
76 while (isIdentifierChar(m_str[m_tokenStart+m_tokenLen]))
77 m_tokenLen += 1;
78 }
79 else
80 TCU_FAIL("Unexpected character");
81 }
82
83 // SubTypeAccess
84
SubTypeAccess(const VarType & type)85 SubTypeAccess::SubTypeAccess (const VarType& type)
86 : m_type(type)
87 {
88 }
89
parseVariableName(const char * nameWithPath)90 std::string parseVariableName (const char* nameWithPath)
91 {
92 VarTokenizer tokenizer(nameWithPath);
93 TCU_CHECK(tokenizer.getToken() == VarTokenizer::TOKEN_IDENTIFIER);
94 return tokenizer.getIdentifier();
95 }
96
parseTypePath(const char * nameWithPath,const VarType & type,TypeComponentVector & path)97 void parseTypePath (const char* nameWithPath, const VarType& type, TypeComponentVector& path)
98 {
99 VarTokenizer tokenizer(nameWithPath);
100
101 if (tokenizer.getToken() == VarTokenizer::TOKEN_IDENTIFIER)
102 tokenizer.advance();
103
104 path.clear();
105 while (tokenizer.getToken() != VarTokenizer::TOKEN_END)
106 {
107 VarType curType = getVarType(type, path);
108
109 if (tokenizer.getToken() == VarTokenizer::TOKEN_PERIOD)
110 {
111 tokenizer.advance();
112 TCU_CHECK(tokenizer.getToken() == VarTokenizer::TOKEN_IDENTIFIER);
113 TCU_CHECK_MSG(curType.isStructType(), "Invalid field selector");
114
115 // Find member.
116 std::string memberName = tokenizer.getIdentifier();
117 int ndx = 0;
118 for (; ndx < curType.getStructPtr()->getNumMembers(); ndx++)
119 {
120 if (memberName == curType.getStructPtr()->getMember(ndx).getName())
121 break;
122 }
123 TCU_CHECK_MSG(ndx < curType.getStructPtr()->getNumMembers(), "Member not found in type");
124
125 path.push_back(VarTypeComponent(VarTypeComponent::STRUCT_MEMBER, ndx));
126 tokenizer.advance();
127 }
128 else if (tokenizer.getToken() == VarTokenizer::TOKEN_LEFT_BRACKET)
129 {
130 tokenizer.advance();
131 TCU_CHECK(tokenizer.getToken() == VarTokenizer::TOKEN_NUMBER);
132
133 int ndx = tokenizer.getNumber();
134
135 if (curType.isArrayType())
136 {
137 TCU_CHECK(de::inBounds(ndx, 0, curType.getArraySize()));
138 path.push_back(VarTypeComponent(VarTypeComponent::ARRAY_ELEMENT, ndx));
139 }
140 else if (curType.isBasicType() && isDataTypeMatrix(curType.getBasicType()))
141 {
142 TCU_CHECK(de::inBounds(ndx, 0, getDataTypeMatrixNumColumns(curType.getBasicType())));
143 path.push_back(VarTypeComponent(VarTypeComponent::MATRIX_COLUMN, ndx));
144 }
145 else if (curType.isBasicType() && isDataTypeVector(curType.getBasicType()))
146 {
147 TCU_CHECK(de::inBounds(ndx, 0, getDataTypeScalarSize(curType.getBasicType())));
148 path.push_back(VarTypeComponent(VarTypeComponent::VECTOR_COMPONENT, ndx));
149 }
150 else
151 TCU_FAIL("Invalid subscript");
152
153 tokenizer.advance();
154 TCU_CHECK(tokenizer.getToken() == VarTokenizer::TOKEN_RIGHT_BRACKET);
155 tokenizer.advance();
156 }
157 else
158 TCU_FAIL("Unexpected token");
159 }
160 }
161
operator <<(std::ostream & str,const TypeAccessFormat & format)162 std::ostream& operator<< (std::ostream& str, const TypeAccessFormat& format)
163 {
164 const VarType* curType = &format.type;
165
166 for (TypeComponentVector::const_iterator iter = format.path.begin(); iter != format.path.end(); iter++)
167 {
168 switch (iter->type)
169 {
170 case VarTypeComponent::ARRAY_ELEMENT:
171 curType = &curType->getElementType(); // Update current type.
172 // Fall-through.
173
174 case VarTypeComponent::MATRIX_COLUMN:
175 case VarTypeComponent::VECTOR_COMPONENT:
176 str << "[" << iter->index << "]";
177 break;
178
179 case VarTypeComponent::STRUCT_MEMBER:
180 {
181 const StructMember& member = curType->getStructPtr()->getMember(iter->index);
182 str << "." << member.getName();
183 curType = &member.getType();
184 break;
185 }
186
187 default:
188 DE_ASSERT(false);
189 }
190 }
191
192 return str;
193 }
194
195 } // glu
196