| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /*************************************** | ||
| 2 | Auteur : Pierre Aubert | ||
| 3 | Mail : pierre.aubert@lapp.in2p3.fr | ||
| 4 | Licence : CeCILL-C | ||
| 5 | ****************************************/ | ||
| 6 | |||
| 7 | #include "PFileParser.h" | ||
| 8 | #include "dico_replace_var.h" | ||
| 9 | |||
| 10 | ///Map used to replace variable value in nested calls (VariableName, PNestedCall) | ||
| 11 | typedef std::vector<std::pair<PNestedCall, DicoValue*> > PVecReplaceVar; | ||
| 12 | ///Map of the variables which uses nested call | ||
| 13 | typedef std::map<PString, std::pair<PNestedCall, DicoValue*> > MapVarWithNestedCall; | ||
| 14 | |||
| 15 | ///Create the nested calls of the input base string | ||
| 16 | /** @param[out] call : PNestedCall to be created | ||
| 17 | * @param baseStr : basic suffix to be used | ||
| 18 | * @param varBegin : characters which announce the begining of a variable (example ${) | ||
| 19 | * @param varEnd : characters which announce the ending of a variable (example }) | ||
| 20 | */ | ||
| 21 | 4 | void dico_create_nested_call(PNestedCall & call, const PString & baseStr, const PString & varBegin, const PString & varEnd){ | |
| 22 |
1/1✓ Branch 0 (2→3) taken 4 times.
|
4 | PFileParser parser; |
| 23 |
1/1✓ Branch 0 (3→4) taken 4 times.
|
4 | parser.setFileContent(baseStr); |
| 24 |
3/3✓ Branch 0 (28→29) taken 9 times.
✓ Branch 2 (29→5) taken 5 times.
✓ Branch 3 (29→30) taken 4 times.
|
9 | while(!parser.isEndOfFile()){ |
| 25 |
1/1✓ Branch 0 (5→6) taken 5 times.
|
5 | PString prevCall(parser.getUntilKeyWithoutPatern(varBegin)); |
| 26 |
3/3✓ Branch 0 (6→7) taken 5 times.
✓ Branch 2 (7→8) taken 4 times.
✓ Branch 3 (7→15) taken 1 times.
|
5 | if(prevCall != ""){ |
| 27 |
1/1✓ Branch 0 (8→9) taken 4 times.
|
4 | PNestedStr str; |
| 28 |
1/1✓ Branch 0 (9→10) taken 4 times.
|
4 | str.setValue(prevCall); |
| 29 |
1/1✓ Branch 0 (10→11) taken 4 times.
|
4 | str.setIsVarCall(false); |
| 30 |
2/2✓ Branch 0 (11→12) taken 4 times.
✓ Branch 2 (12→13) taken 4 times.
|
4 | call.getVecNestedStr().push_back(str); |
| 31 | 4 | } | |
| 32 |
1/1✓ Branch 0 (15→16) taken 5 times.
|
5 | PString varNameCall(parser.getUntilKeyWithoutPatern(varEnd)); |
| 33 |
3/3✓ Branch 0 (16→17) taken 5 times.
✓ Branch 2 (17→18) taken 4 times.
✓ Branch 3 (17→25) taken 1 times.
|
5 | if(varNameCall != ""){ |
| 34 |
1/1✓ Branch 0 (18→19) taken 4 times.
|
4 | PNestedStr str; |
| 35 |
1/1✓ Branch 0 (19→20) taken 4 times.
|
4 | str.setValue(varNameCall); |
| 36 |
1/1✓ Branch 0 (20→21) taken 4 times.
|
4 | str.setIsVarCall(true); |
| 37 |
2/2✓ Branch 0 (21→22) taken 4 times.
✓ Branch 2 (22→23) taken 4 times.
|
4 | call.getVecNestedStr().push_back(str); |
| 38 | 4 | } | |
| 39 | 5 | } | |
| 40 | 4 | } | |
| 41 | |||
| 42 | ///Replace the nested call by the variables in map | ||
| 43 | /** @param[out] out : output string with replaced variables | ||
| 44 | * @param call : nested call to create the output string | ||
| 45 | * @param mapKeyVariable : map of all defined variabled to be used | ||
| 46 | * @param varBegin : characters which announce the begining of a variable (example ${) (in case variable is not found) | ||
| 47 | * @param varEnd : characters which announce the ending of a variable (example }) (in case variable is not found) | ||
| 48 | */ | ||
| 49 | 4 | void dico_replace_nested_call(PString & out, const PNestedCall & call, const PMapKnownVar & mapKeyVariable, const PString & varBegin, const PString & varEnd){ | |
| 50 | 4 | const std::vector<PNestedStr> & vecNestedStr = call.getVecNestedStr(); | |
| 51 |
2/2✓ Branch 0 (47→4) taken 8 times.
✓ Branch 1 (47→48) taken 4 times.
|
24 | for(std::vector<PNestedStr>::const_iterator it(vecNestedStr.begin()); it != vecNestedStr.end(); ++it){ |
| 52 |
3/3✓ Branch 0 (6→7) taken 8 times.
✓ Branch 2 (7→8) taken 4 times.
✓ Branch 3 (7→33) taken 4 times.
|
8 | if(it->getIsVarCall()){ |
| 53 |
5/5✓ Branch 0 (10→11) taken 4 times.
✓ Branch 2 (11→12) taken 4 times.
✓ Branch 4 (12→13) taken 4 times.
✓ Branch 6 (13→14) taken 4 times.
✓ Branch 8 (14→15) taken 4 times.
|
8 | PMapKnownVar::const_iterator itCall(mapKeyVariable.find(varBegin + it->getValue() + varEnd)); |
| 54 |
2/2✓ Branch 0 (20→21) taken 3 times.
✓ Branch 1 (20→23) taken 1 times.
|
4 | if(itCall != mapKeyVariable.end()){ |
| 55 |
1/1✓ Branch 0 (22→32) taken 3 times.
|
3 | out += itCall->second; |
| 56 | }else{ | ||
| 57 |
4/4✓ Branch 0 (25→26) taken 1 times.
✓ Branch 2 (26→27) taken 1 times.
✓ Branch 4 (27→28) taken 1 times.
✓ Branch 6 (28→29) taken 1 times.
|
2 | out += varBegin + it->getValue() + varEnd; |
| 58 | } | ||
| 59 | }else{ | ||
| 60 |
2/2✓ Branch 0 (35→36) taken 4 times.
✓ Branch 2 (36→37) taken 4 times.
|
4 | out += it->getValue(); |
| 61 | } | ||
| 62 | } | ||
| 63 | 4 | } | |
| 64 | |||
| 65 | ///Update the suffix of the file | ||
| 66 | /** @param baseStr : basic suffix to be used | ||
| 67 | * @param mapKeyVariable : map of all defined variabled to be used | ||
| 68 | * @param varBegin : characters which announce the begining of a variable (example ${) | ||
| 69 | * @param varEnd : characters which announce the ending of a variable (example }) | ||
| 70 | * @return updated string | ||
| 71 | */ | ||
| 72 | 7 | PString dico_replace_var_str(const PString & baseStr, const PMapKnownVar & mapKeyVariable, const PString & varBegin, const PString & varEnd){ | |
| 73 |
9/9✓ Branch 0 (2→3) taken 7 times.
✓ Branch 2 (3→4) taken 5 times.
✓ Branch 3 (3→6) taken 2 times.
✓ Branch 4 (4→5) taken 5 times.
✓ Branch 6 (5→6) taken 1 times.
✓ Branch 7 (5→7) taken 4 times.
✓ Branch 8 (8→9) taken 3 times.
✓ Branch 9 (8→11) taken 4 times.
✓ Branch 10 (9→10) taken 3 times.
|
7 | if(varBegin == "" || varEnd == ""){return baseStr;} |
| 74 |
1/1✓ Branch 0 (11→12) taken 4 times.
|
4 | PNestedCall call; |
| 75 |
1/1✓ Branch 0 (12→13) taken 4 times.
|
4 | dico_create_nested_call(call, baseStr, varBegin, varEnd); |
| 76 |
1/1✓ Branch 0 (13→14) taken 4 times.
|
4 | PString out(""); |
| 77 |
1/1✓ Branch 0 (14→15) taken 4 times.
|
4 | dico_replace_nested_call(out, call, mapKeyVariable, varBegin, varEnd); |
| 78 |
1/1✓ Branch 0 (15→16) taken 4 times.
|
4 | return out; |
| 79 | 4 | } | |
| 80 | |||
| 81 | ///Create the PNestedCall from the given value | ||
| 82 | /** @param[out] call : PNestedCall | ||
| 83 | * @param value : value to be used | ||
| 84 | * @param varName : name of the variable to be defined | ||
| 85 | * @param varBegin : characters which announce the begining of a variable (example ${) | ||
| 86 | * @param varEnd : characters which announce the ending of a variable (example }) | ||
| 87 | * @return true if the value contains a nested call, false otherwise | ||
| 88 | */ | ||
| 89 | ✗ | bool createNestedCallFromStr(PNestedCall & call, const PString & value, const PString varName, const PString & varBegin, const PString & varEnd){ | |
| 90 | ✗ | call.setName(varName); | |
| 91 | ✗ | PFileParser parser; | |
| 92 | ✗ | parser.setFileContent(value); | |
| 93 | ✗ | bool hasNestedCall(false); | |
| 94 | ✗ | while(!parser.isEndOfFile()){ | |
| 95 | ✗ | PString prevCall(parser.getUntilKeyWithoutPatern(varBegin)); | |
| 96 | ✗ | if(prevCall != ""){ | |
| 97 | ✗ | PNestedStr str; | |
| 98 | ✗ | str.setValue(prevCall); | |
| 99 | ✗ | str.setIsVarCall(false); | |
| 100 | ✗ | call.getVecNestedStr().push_back(str); | |
| 101 | ✗ | } | |
| 102 | ✗ | PString varNameCall(parser.getUntilKeyWithoutPatern(varEnd)); | |
| 103 | ✗ | if(varNameCall != ""){ | |
| 104 | ✗ | PNestedStr str; | |
| 105 | ✗ | str.setValue(varNameCall); | |
| 106 | ✗ | str.setIsVarCall(true); | |
| 107 | ✗ | call.getVecNestedStr().push_back(str); | |
| 108 | ✗ | hasNestedCall = true; | |
| 109 | ✗ | } | |
| 110 | ✗ | } | |
| 111 | ✗ | return hasNestedCall; | |
| 112 | ✗ | } | |
| 113 | |||
| 114 | ///Get the variable which contains only a value and those with nested calls | ||
| 115 | /** @param[out] mapReadyVar : map of variables with values only | ||
| 116 | * @param[out] mapNestedVar : map of variables with nested calls | ||
| 117 | * @param[out] mapVarWithNestedCall : map of the variables which use nested calls | ||
| 118 | * @param varIdentifier : String used to detect the variable names (example: '$' for ${varName}, § for §{varName}) | ||
| 119 | * @param dico : DicoValue to be used | ||
| 120 | */ | ||
| 121 | ✗ | void dico_find_all_var(PMapKnownVar & mapReadyVar, PVecReplaceVar & mapNestedVar, MapVarWithNestedCall & mapVarWithNestedCall, DicoValue & dico, const PString & varIdentifier){ | |
| 122 | ✗ | if(dico.hasMap()){ | |
| 123 | ✗ | MapDicoValue & mapDico = dico.getMapChild(); | |
| 124 | ✗ | for(MapDicoValue::iterator it(mapDico.begin()); it != mapDico.end(); ++it){ | |
| 125 | ✗ | dico_find_all_var(mapReadyVar, mapNestedVar, mapVarWithNestedCall, it->second, varIdentifier); | |
| 126 | } | ||
| 127 | ✗ | }else if(dico.hasVec()){ | |
| 128 | ✗ | VecDicoValue & vecDico = dico.getVecChild(); | |
| 129 | ✗ | for(VecDicoValue::iterator it(vecDico.begin()); it != vecDico.end(); ++it){ | |
| 130 | ✗ | dico_find_all_var(mapReadyVar, mapNestedVar, mapVarWithNestedCall, *it, varIdentifier); | |
| 131 | } | ||
| 132 | ✗ | }else if(dico.hasKey()){ //No map, no vector but a key, this is a string variable | |
| 133 | ✗ | PString strValue(dico.getString()), varName(dico.getKey()); | |
| 134 | //Let's check is the value contains nested calls | ||
| 135 | //We will create a class to handle the split between string part and nested calls | ||
| 136 | ✗ | PNestedCall call; | |
| 137 | //We add the class in the proper map | ||
| 138 | ✗ | if((createNestedCallFromStr(call, strValue, varName, varIdentifier + "{", "}"))){ //There is (at least) one nested call | |
| 139 | ✗ | mapNestedVar.push_back(std::pair<PNestedCall, DicoValue*>(call, &dico)); | |
| 140 | ✗ | mapVarWithNestedCall[varName] = std::pair<PNestedCall, DicoValue*>(call, &dico); | |
| 141 | }else{ //There is no nested call | ||
| 142 | ✗ | mapReadyVar[varName] = strValue; | |
| 143 | } | ||
| 144 | ✗ | } | |
| 145 | ✗ | } | |
| 146 | |||
| 147 | |||
| 148 | ///Update variables with nested calls | ||
| 149 | /** @param[out] mapReadyVar : map of variables with values only | ||
| 150 | * @param[out] mapNestedVar : map of variables with nested calls | ||
| 151 | * @param nestedCall : nested call which is the split value of the dico | ||
| 152 | * @param mapVarWithNestedCall : map of the variables which use nested calls | ||
| 153 | * @param dico : DicoValue to be used | ||
| 154 | * @param varIdentifier : String used to detect the variable names (example: '$' for ${varName}, § for §{varName}) | ||
| 155 | */ | ||
| 156 | ✗ | void dico_update_all_nestedCall(PMapKnownVar & mapReadyVar, PVecReplaceVar & mapNestedVar, MapVarWithNestedCall & mapVarWithNestedCall, | |
| 157 | PNestedCall & nestedCall, DicoValue * dico, const PString & varIdentifier) | ||
| 158 | { | ||
| 159 | //For each call, we check if it comes from the mapReadyVar, from the mapNestedVar or from nowhere | ||
| 160 | ✗ | PString outputValue(""); | |
| 161 | ✗ | std::vector<PNestedStr> & vecNestedStr = nestedCall.getVecNestedStr(); | |
| 162 | ✗ | for(std::vector<PNestedStr>::iterator it(vecNestedStr.begin()); it != vecNestedStr.end(); ++it){ | |
| 163 | ✗ | if(!it->getIsVarCall()){ //If it is not a var call, we skip it | |
| 164 | ✗ | outputValue += it->getValue(); | |
| 165 | ✗ | continue; | |
| 166 | } | ||
| 167 | ✗ | PString varName(it->getValue()); | |
| 168 | //If the var comes from mapNestedVar, we have to resolve this one first | ||
| 169 | ✗ | MapVarWithNestedCall::iterator itNested = mapVarWithNestedCall.find(varName); | |
| 170 | ✗ | if(itNested != mapVarWithNestedCall.end()){ | |
| 171 | ✗ | dico_update_all_nestedCall(mapReadyVar, mapNestedVar, mapVarWithNestedCall, itNested->second.first, itNested->second.second, varIdentifier); | |
| 172 | ✗ | mapVarWithNestedCall.erase(varName); //We solve varName, so we erase it from the mapNestedVar | |
| 173 | //But now, the varName entry does exist in the mapReadyVar | ||
| 174 | } | ||
| 175 | //If the var comes from mapReadyVar, we replace it | ||
| 176 | ✗ | PMapKnownVar::iterator itReady = mapReadyVar.find(varName); | |
| 177 | ✗ | if(itReady != mapReadyVar.end()){ | |
| 178 | ✗ | outputValue += itReady->second; | |
| 179 | }else{ | ||
| 180 | //If we cannot find it, let's keep it unsolved (it can we a global variable) | ||
| 181 | ✗ | outputValue += varIdentifier + "{" + varName + "}"; | |
| 182 | } | ||
| 183 | ✗ | } | |
| 184 | //Finally, we can update the dico value, but we deal with the quotation | ||
| 185 | ✗ | PString firstQuote(""), prevValue(dico->getValue()); | |
| 186 | ✗ | if(prevValue.size() != 0lu){ | |
| 187 | ✗ | if(prevValue.front() == '\''){firstQuote = "'";} | |
| 188 | ✗ | else if(prevValue.front() == '"'){firstQuote = "\"";} | |
| 189 | } | ||
| 190 | ✗ | dico->setValue(firstQuote + outputValue + firstQuote); | |
| 191 | |||
| 192 | //And put its value into the mapReadyVar, because we solve it | ||
| 193 | ✗ | mapReadyVar[nestedCall.getName()] = outputValue; | |
| 194 | ✗ | } | |
| 195 | |||
| 196 | ///Update the variable which contains nested calls | ||
| 197 | /** @param[out] mapReadyVar : map of variables with values only | ||
| 198 | * @param[out] mapNestedVar : map of variables with nested calls | ||
| 199 | * @param mapVarWithNestedCall : map of variable with nested call | ||
| 200 | * @param varIdentifier : String used to detect the variable names (example: '$' for ${varName}, § for §{varName}) | ||
| 201 | */ | ||
| 202 | ✗ | void dico_update_all_var(PMapKnownVar & mapReadyVar, PVecReplaceVar & mapNestedVar, MapVarWithNestedCall & mapVarWithNestedCall, | |
| 203 | const PString & varIdentifier) | ||
| 204 | { | ||
| 205 | //Let's try to complete the nested call | ||
| 206 | ✗ | for(PVecReplaceVar::iterator itNested(mapNestedVar.begin()); itNested != mapNestedVar.end(); ++itNested){ | |
| 207 | ✗ | PNestedCall & nestedCall = itNested->first; | |
| 208 | ✗ | DicoValue * dico = itNested->second; | |
| 209 | |||
| 210 | ✗ | dico_update_all_nestedCall(mapReadyVar, mapNestedVar, mapVarWithNestedCall, nestedCall, dico, varIdentifier); | |
| 211 | } | ||
| 212 | ✗ | } | |
| 213 | |||
| 214 | ///Replace all the variables which are string in the given DicoValue, when ${variable} apprears in the value | ||
| 215 | /** @param dico : DicoValue to be updated | ||
| 216 | * @param varIdentifier : String used to detect the variable names (example: '$' for ${varName}, § for §{varName}) | ||
| 217 | */ | ||
| 218 | ✗ | void dico_replace_var(DicoValue & dico, const PString & varIdentifier){ | |
| 219 | //Let's find all the defined variables, linked to the DicoValue, string only | ||
| 220 | ✗ | PMapKnownVar mapReadyVar; | |
| 221 | ✗ | PVecReplaceVar mapNestedVar; | |
| 222 | ✗ | MapVarWithNestedCall mapVarWithNestedCall; | |
| 223 | ✗ | dico_find_all_var(mapReadyVar, mapNestedVar, mapVarWithNestedCall, dico, varIdentifier); | |
| 224 | |||
| 225 | //Update variables with nested call, separate those with nested call from the other | ||
| 226 | ✗ | dico_update_all_var(mapReadyVar, mapNestedVar, mapVarWithNestedCall, varIdentifier); | |
| 227 | ✗ | } | |
| 228 | |||
| 229 | |||
| 230 |