Home | History | Annotate | Download | only in opengl
      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 
     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 
     42 int VarTokenizer::getNumber (void) const
     43 {
     44 	return atoi(getIdentifier().c_str());
     45 }
     46 
     47 static inline bool	isNum				(char c) { return de::inRange(c, '0', '9'); }
     48 static inline bool	isAlpha				(char c) { return de::inRange(c, 'a', 'z') || de::inRange(c, 'A', 'Z');	}
     49 static inline bool	isIdentifierChar	(char c) { return isAlpha(c) || isNum(c) || c == '_'; }
     50 
     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 
     85 SubTypeAccess::SubTypeAccess (const VarType& type)
     86 	: m_type(type)
     87 {
     88 }
     89 
     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 
     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 
    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