* ** This library is free software; you can redistribute it and/or modify it ** under the terms of the GNU Lesser General Public License as published by the ** Free Software Foundation; either version 2.1 of the License, or (at your ** option) any later version. ** ** This library is distributed in the hope that it will be useful, but WITHOUT ** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ** FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License ** for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this library; if not, write to the Free Software Foundation, ** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ** *

caseVERTEX_SHADER:if(!srcInsertCodeBeforeMainFunction(insertedCode,m_vShaderMutation)){CGoGNerr<<"ERROR - "<<"ShaderMutator::insertCodeBeforeMainFunction : "<<"Unable to insert source code in vertex shader of "<<m_shaderName<<". You should check if the shader has a main function declaration"<<CGoGNendl;

}break;caseFRAGMENT_SHADER:if(!srcInsertCodeBeforeMainFunction(insertedCode,m_fShaderMutation)){CGoGNerr<<"ERROR - "<<"ShaderMutator::insertCodeBeforeMainFunction : "<<"Unable to insert source code in fragment shader of "<<m_shaderName<<". You should check if the shader has a main function declaration"<<CGoGNendl;

}break;caseGEOMETRY_SHADER:if(!srcInsertCodeBeforeMainFunction(insertedCode,m_gShaderMutation)){CGoGNerr<<"ERROR - "<<"ShaderMutator::insertCodeBeforeMainFunction : "<<"Unable to insert source code in geometry shader of "<<m_shaderName<<". You should check if the shader has a main function declaration"<<CGoGNendl;

caseVERTEX_SHADER:if(!srcInsertCodeAtMainFunctionBeginning(insertedCode,m_vShaderMutation)){CGoGNerr<<"ERROR - "<<"ShaderMutator::insertCodeAtMainFunctionBeginnning : "<<"Unable to insert source code in vertex shader of "<<m_shaderName<<". You should check if the shader has a main function declaration"<<CGoGNendl;

}break;caseFRAGMENT_SHADER:if(!srcInsertCodeAtMainFunctionBeginning(insertedCode,m_fShaderMutation)){CGoGNerr<<"ERROR - "<<"ShaderMutator::insertCodeAtMainFunctionBeginnning : "<<"Unable to insert source code in fragment shader of "<<m_shaderName<<". You should check if the shader has a main function declaration"<<CGoGNendl;

}break;caseGEOMETRY_SHADER:if(!srcInsertCodeAtMainFunctionBeginning(insertedCode,m_gShaderMutation)){CGoGNerr<<"ERROR - "<<"ShaderMutator::insertCodeAtMainFunctionBeginnning : "<<"Unable to insert source code in geometry shader of "<<m_shaderName<<". You should check if the shader has a main function declaration"<<CGoGNendl;

caseVERTEX_SHADER:if(!srcInsertCodeAtMainFunctionEnd(insertedCode,m_vShaderMutation)){CGoGNerr<<"ERROR - "<<"ShaderMutator::insertCodeAtMainFunctionEnd : "<<"Unable to insert source code in vertex shader of "<<m_shaderName<<". You should check if the shader has a main function declaration "<<"and as many '{' as '}' in main"<<CGoGNendl;

caseFRAGMENT_SHADER:if(!srcInsertCodeAtMainFunctionEnd(insertedCode,m_fShaderMutation)){CGoGNerr<<"ERROR - "<<"ShaderMutator::insertCodeAtMainFunctionEnd : "<<"Unable to insert source code in fragment shader of "<<m_shaderName<<". You should check if the shader has a main function declaration "<<"and as many '{' as '}' in main"<<CGoGNendl;

caseGEOMETRY_SHADER:if(!srcInsertCodeAtMainFunctionEnd(insertedCode,m_gShaderMutation)){CGoGNerr<<"ERROR - "<<"ShaderMutator::insertCodeAtMainFunctionEnd : "<<"Unable to insert source code in geometry shader of "<<m_shaderName<<". You should check if the shader has a main function declaration "<<"and as many '{' as '}' in main"<<CGoGNendl;

{// Regular expression for variable declaration// <',' OR white-space[1 or more times]> <variableName> <',' OR ';' OR white-space>boost::regexvar_re("(,|\\s+)"+variableName+"(,|;|\\s)");// Matches resultsboost::match_results<std::string::iterator>matches;// Search for the first expression that matches and isn't commentedstd::string::iteratorstart=src.begin();std::string::iteratorend=src.end();while(regex_search(start,end,matches,var_re,boost::format_first_only)){// Start position of the matchsize_tstartPosition=std::distance(src.begin(),matches[0].first);// Finish if the matched variable is the good one (i.e. not commented)

// Matches resultsboost::match_results<std::string::iterator>matches;// Build the version stringstd::stringversionStr;std::stringstreamss;ss<<version;versionStr=ss.str();// Search for the first expression that matches and isn't commentedstd::string::iteratorstart=modifiedSrc.begin();std::string::iteratorend=modifiedSrc.end();while(regex_search(start,end,matches,version_re,boost::format_first_only)){// Start position of the matchsize_tstartPosition=std::distance(modifiedSrc.begin(),matches[0].first);// Change the version number if the matched "#version ..." is the good one (i.e. not commented)

if(oldVersionValue<version){modifiedSrc.replace(oldVersionPosition,oldVersionLength,versionStr);returntrue;}elsereturnfalse;}// Else continue to search for it after last matchelse{start=matches[0].second;}}// At this point no correct match was found : insert directly the "#version ..." linestd::stringversionLineStr="#version "+versionStr+"\n";modifiedSrc.insert(0,versionLineStr);returntrue;}

// Search for the first expression that matches and isn't commentedstd::string::iteratorstart=modifiedSrc.begin();std::string::iteratorend=modifiedSrc.end();while(regex_search(start,end,matches,const_re,boost::format_first_only)){// Start position of the matchsize_tstartPosition=std::distance(modifiedSrc.begin(),matches[0].first);// Change the constant value if the matched "#define ..." is the good one (i.e. not commented)if(!srcIsCommented(startPosition,modifiedSrc)){// The submatch Match[1] should be the old constant valuestd::stringoldValStr(matches[1].first,matches[1].second);size_toldValLength=oldValStr.length();size_toldValPosition=std::distance(modifiedSrc.begin(),matches[1].first);// Replace the old constant valuemodifiedSrc.replace(oldValPosition,oldValLength,newValStr);returntrue;}// Else continue to search for it after last matchelse{start=matches[0].second;}}// At this point no correct match was foundreturnfalse;}boolShaderMutator::srcChangeFloatConstantValue(floatnewVal,conststd::string&constantName,std::string&modifiedSrc){// Regular expression for constant expression// <#define> <white-space>[1 or more times] <constant name> <white-space>[1 or more times]// <digit>[1 or more times] <.>[0 or 1 time] <digit>[0 or more times]boost::regexconst_re("#define\\s+"+constantName+"\\s+(\\d+\\.?\\d*)");// Matches resultsboost::match_results<std::string::iterator>matches;// Build the constant value stringstd::stringnewValStr;std::stringstreamss;ss<<newVal;newValStr=ss.str();

// Search for the first expression that matches and isn't commentedstd::string::iteratorstart=modifiedSrc.begin();std::string::iteratorend=modifiedSrc.end();while(regex_search(start,end,matches,const_re,boost::format_first_only)){// Start position of the matchsize_tstartPosition=std::distance(modifiedSrc.begin(),matches[0].first);// Change the constant value if the matched "#define ..." is the good one (i.e. not commented)if(!srcIsCommented(startPosition,modifiedSrc)){// The submatch Match[1] should be the old constant valuestd::stringoldValStr(matches[1].first,matches[1].second);size_toldValLength=oldValStr.length();size_toldValPosition=std::distance(modifiedSrc.begin(),matches[1].first);

modifiedSrc.replace(oldValPosition,oldValLength,newValStr);returntrue;}// Else continue to search for it after last matchelse{start=matches[0].second;}}// At this point no correct match was foundreturnfalse;}boolShaderMutator::srcInsertCodeBeforeMainFunction(conststd::string&insertedCode,std::string&modifiedSrc)

{// Regular expression for main function// <void> <white-space>[1 or more times] <main> <white-space>[0 or more times] <'('>boost::regexmain_re("(void)\\s+(main)\\s*\\(");// Matches resultsboost::match_results<std::string::iterator>matches;// Search for the first expression that matches and isn't commentedstd::string::iteratorstart=modifiedSrc.begin();std::string::iteratorend=modifiedSrc.end();while(regex_search(start,end,matches,main_re,boost::format_first_only)){// Start position of the matchsize_tstartPosition=std::distance(modifiedSrc.begin(),matches[0].first);// Insert and finish if the matched "main" is the good one (i.e. not commented)

{// Regular expression for main function// <void> <white-space>[1 or more times] <main> <white-space>[0 or more times]// <'('> <white-space>[0 or more times] <')'>// <white-space>[0 or more times] <'{'>boost::regexmain_re("(void)\\s+(main)\\s*\\(\\s*\\)\\s*\\{");// Matches resultsboost::match_results<std::string::iterator>matches;// Search for the first expression that matches and isn't commentedstd::string::iteratorstart=modifiedSrc.begin();std::string::iteratorend=modifiedSrc.end();while(regex_search(start,end,matches,main_re,boost::format_first_only)){// Start position of the matchsize_tstartPosition=std::distance(modifiedSrc.begin(),matches[0].first);// End position of the matchsize_tendPosition=std::distance(modifiedSrc.begin(),matches[0].second);// Insert and finish if the matched "main" is the good one (i.e. not commented)

{// Regular expression for main function// <void> <white-space>[1 or more times] <main> <white-space>[0 or more times]// <'('> <white-space>[0 or more times] <')'>// <white-space>[0 or more times] <'{'>boost::regexmain_re("(void)\\s+(main)\\s*\\(\\s*\\)\\s*\\{");// Matches resultsboost::match_results<std::string::iterator>matches;// Search for the first expression that matches and isn't commentedstd::string::iteratorstart=modifiedSrc.begin();std::string::iteratorend=modifiedSrc.end();

while(regex_search(start,end,matches,main_re,boost::format_first_only)&&(mainFirstBracePos==0)){// Start position of the matchsize_tstartPosition=std::distance(modifiedSrc.begin(),matches[0].first);// End position of the matchsize_tendPosition=std::distance(modifiedSrc.begin(),matches[0].second);// Get the main first brace position if the matched "main" is the good one (i.e. not commented)

mainFirstBracePos=endPosition;// Else continue to search for it after last matchelsestart=matches[0].second;}// If mainFirstBracePos is still zero, no correct match was foundif(mainFirstBracePos==0)returnfalse;// Else, it is now possible to count the opening and closing braces till the final closing brace of the main function is reachedintbracesCounter=1;// =1 since the first opening brace is counted in, it will be =0 when the final closing brace is reachedsize_tclosestBracePos=mainFirstBracePos;size_tclosestOpeningBracePos;size_tclosestClosingBracePos;while(bracesCounter!=0){closestOpeningBracePos=modifiedSrc.find_first_of('{',closestBracePos+1);// If this brace appears to be commented, try to get the next one

closestOpeningBracePos=modifiedSrc.find_first_of('{',closestOpeningBracePos+1);closestClosingBracePos=modifiedSrc.find_first_of('}',closestBracePos+1);// If this brace appears to be commented, try to get the next one

closestClosingBracePos=modifiedSrc.find_first_of('}',closestClosingBracePos+1);// Happens if there is not enough "}" for the corresponding "{"if(closestClosingBracePos==std::string::npos)returnfalse;// Refresh the closest brace position, and increment or decrement the counterif(closestClosingBracePos<closestOpeningBracePos){closestBracePos=closestClosingBracePos;bracesCounter-=1;}else{closestBracePos=closestOpeningBracePos;bracesCounter+=1;}}// We should now have the final '}' of the main functionsize_tmainLastBracePos=closestBracePos;// Insert the source theremodifiedSrc.insert(mainLastBracePos,insertedCode);returntrue;}}// namespace Utils}// namespace CGoGN