//--------------------------------------------------------------------------------------------------------------- // This function checks if argument is constant. If it is it returns true, overwise false //--------------------------------------------------------------------------------------------------------------- static bool GetConstantIDFromArgument(gtASCIIString sArgument, gtASCIIString cKey, unsigned int& nSlotID) { unsigned int nKeyPosition = (unsigned int)sArgument.find(cKey); // Check if cKey is not end of other argument if (nKeyPosition == std::string::npos || (nKeyPosition != 0 && sArgument[nKeyPosition - 1] != '>' // code can be in HTML && sArgument[nKeyPosition - 1] != ' ')) { return false; } // End of if // Looking for not digital symbols in argument unsigned int nNextNotDigit = (unsigned int)sArgument.find_first_not_of("0123456789", nKeyPosition + cKey.length()); gtASCIIString sSlotID; // this variable contains string with the slot number if (nNextNotDigit == std::string::npos) // All character after cKey are digits { sSlotID = sArgument.substr(nKeyPosition + cKey.length()); } // End of if // Check if the variable is finished with digit else if ((sArgument[nNextNotDigit] != '<' && sArgument[nNextNotDigit] != ' ' && sArgument[nNextNotDigit] != ',' && sArgument[nNextNotDigit] != '.' && sArgument[nNextNotDigit] != '[' && sArgument[nNextNotDigit] != '\n') || nNextNotDigit <= nKeyPosition + 1) { return false; } // End of else if else { sSlotID = sArgument.substr(nKeyPosition + cKey.length(), nNextNotDigit - nKeyPosition - cKey.length()); } // End of else int nScanRes = sscanf_s(sSlotID.asCharArray(), "%d", &nSlotID); if (nScanRes < 1) { Log(logERROR, "%s: Failed to read integer from Str = %s\n", __FUNCTION__, sSlotID.asCharArray()); return false; } return true; }// End of GetConstantIDFromArgument
//--------------------------------------------------------------------------------------------------------------- // This function returns of slots used in code // cKey is symbol which shows what kind of slots are requested: 'c' for float constants, 'b' for boolean // constants etc. Results are kept in usedSlots. //--------------------------------------------------------------------------------------------------------------- long GetConstantsFromCode(gtASCIIString code, gtASCIIString cKey, std::list<unsigned long>& usedSlots) { long hr = 0; typedef std::map< gtASCIIString, std::vector<unsigned long> > ArgumentType; typedef std::map< gtASCIIString, std::vector<unsigned long> >::iterator ArgumentIter; ArgumentType ArgumentLength; ArgumentIter ArgIter; // This map contains infoemation about arguments lenth // i.e the third argument of the m4x4 itstruction is 4x4 matrix, // which uses 4 slots, so if shader has instruction m4x4 oPos, v0, c0 it means // c0, c1, c3 and c4 are used, that is why ArgumentLength["m4x4"][2] = 4 ArgumentLength["m3x2"].resize(3); ArgumentLength["m3x2"][0] = 1; ArgumentLength["m3x2"][1] = 1; ArgumentLength["m3x2"][2] = 2; ArgumentLength["m3x3"].resize(3); ArgumentLength["m3x3"][0] = 1; ArgumentLength["m3x3"][1] = 1; ArgumentLength["m3x3"][2] = 3; ArgumentLength["m3x4"].resize(3); ArgumentLength["m3x4"][0] = 1; ArgumentLength["m3x4"][1] = 1; ArgumentLength["m3x4"][2] = 4; ArgumentLength["m4x3"].resize(3); ArgumentLength["m4x3"][0] = 1; ArgumentLength["m4x3"][1] = 1; ArgumentLength["m4x3"][2] = 3; ArgumentLength["m4x4"].resize(3); ArgumentLength["m4x4"][0] = 1; ArgumentLength["m4x4"][1] = 1; ArgumentLength["m4x4"][2] = 4; ArgumentLength["texm3x2depth"].resize(2); ArgumentLength["texm3x2depth"][0] = 3; ArgumentLength["texm3x2depth"][1] = 2; ArgumentLength["texm3x2pad"].resize(2); ArgumentLength["texm3x2pad"][0] = 3; ArgumentLength["texm3x2pad"][1] = 2; ArgumentLength["texm3x2tex"].resize(2); ArgumentLength["texm3x2tex"][0] = 3; ArgumentLength["texm3x2tex"][1] = 2; ArgumentLength["texm3x3"].resize(2); ArgumentLength["texm3x3"][0] = 3; ArgumentLength["texm3x3"][1] = 3; ArgumentLength["texm3x3pad"].resize(2); ArgumentLength["texm3x3pad"][0] = 3; ArgumentLength["texm3x3pad"][1] = 3; ArgumentLength["texm3x3spec"].resize(2); ArgumentLength["texm3x3spec"][0] = 3; ArgumentLength["texm3x3spec"][1] = 3; ArgumentLength["texm3x3tex"].resize(2); ArgumentLength["texm3x3tex"][0] = 3; ArgumentLength["texm3x3tex"][1] = 3; ArgumentLength["texm3x3vspec"].resize(2); ArgumentLength["texm3x3vspec"][0] = 3; ArgumentLength["texm3x3vspec"][1] = 3; unsigned int nStartOfToken = 0; // This loop splits code to tokens while (nStartOfToken != std::string::npos) { unsigned int nNextToken = (unsigned int)code.find('\n', nStartOfToken + 1); // comment gtASCIIString sToken = (nNextToken == std::string::npos) ? code.substr(nStartOfToken) : code.substr(nStartOfToken, nNextToken - nStartOfToken); if (sToken.length() > 1 && sToken.substr(0, 1) != "//") // Skip comments and empty strings { unsigned int nStartOfInstruction = (unsigned int)sToken.find_first_not_of(" \n", 0); // comment unsigned int nEndOfInstruction = (unsigned int)sToken.find(' ', nStartOfInstruction); if (nEndOfInstruction == std::string::npos) { nStartOfToken = nNextToken; continue; } gtASCIIString sCommand = sToken.substr(nStartOfInstruction, nEndOfInstruction - nStartOfInstruction); unsigned int nArgument = 0; unsigned int nStartOfArgument = nEndOfInstruction + 1; unsigned int nEndOfArgument; do // This separates arguments of command { nEndOfArgument = (unsigned int)sToken.find(',', nStartOfArgument); gtASCIIString sArgument = (nEndOfArgument == std::string::npos) ? sToken.substr(nStartOfArgument) : sToken.substr(nStartOfArgument, nEndOfArgument - nStartOfArgument); unsigned int nSlotID; if (GetConstantIDFromArgument(sArgument, cKey, nSlotID) == false) { nArgument++; nStartOfArgument = nEndOfArgument + 1; continue; } // Calculation of used constants. Default is 1. Next 2 lines check if the command in "special cases map" ArgIter = ArgumentLength.find(sCommand); int nArgsCount = (ArgIter == ArgumentLength.end()) ? 1 : // If coommand has not been find the lenth of argument is supposed 1 (ArgIter->second.size() > nArgument ? ArgIter->second[nArgument] : 1); // If there no information for considered argument its lenth is supposed 1 // This loop adds variables in the used constants list for (unsigned int i = nSlotID; i < nSlotID + nArgsCount; i++) { bool nNotFind = true; for (std::list<unsigned long>::const_iterator iter = usedSlots.begin(); iter != usedSlots.end(); ++iter) { if (*iter == i) { nNotFind = false; break; } } if (nNotFind) { usedSlots.push_back(i); } // End of if }// End of for nArgument++; nStartOfArgument = nEndOfArgument + 1; } while (nEndOfArgument != std::string::npos); } // End of if ( sToken.size() > 1 && sToken.substr( 0, 1 ) != "//" ) nStartOfToken = nNextToken; }// End of while ( nFound != string::npos ) return hr; }// End of GetConstantsFromCode