Directory: | ./ |
---|---|
File: | tmp_project/PhoenixFileParser/src/dico_replace_var.cpp |
Date: | 2025-03-14 11:45:13 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 38 | 107 | 35.5% |
Branches: | 54 | 222 | 24.3% |
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 1 taken 4 times.
|
4 | PFileParser parser; |
23 |
1/1✓ Branch 1 taken 4 times.
|
4 | parser.setFileContent(baseStr); |
24 |
3/3✓ Branch 1 taken 9 times.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 4 times.
|
9 | while(!parser.isEndOfFile()){ |
25 |
1/1✓ Branch 1 taken 5 times.
|
5 | PString prevCall(parser.getUntilKeyWithoutPatern(varBegin)); |
26 |
3/3✓ Branch 1 taken 5 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 1 times.
|
5 | if(prevCall != ""){ |
27 |
1/1✓ Branch 1 taken 4 times.
|
4 | PNestedStr str; |
28 |
1/1✓ Branch 1 taken 4 times.
|
4 | str.setValue(prevCall); |
29 |
1/1✓ Branch 1 taken 4 times.
|
4 | str.setIsVarCall(false); |
30 |
2/2✓ Branch 1 taken 4 times.
✓ Branch 4 taken 4 times.
|
4 | call.getVecNestedStr().push_back(str); |
31 | 4 | } | |
32 |
1/1✓ Branch 1 taken 5 times.
|
5 | PString varNameCall(parser.getUntilKeyWithoutPatern(varEnd)); |
33 |
3/3✓ Branch 1 taken 5 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 1 times.
|
5 | if(varNameCall != ""){ |
34 |
1/1✓ Branch 1 taken 4 times.
|
4 | PNestedStr str; |
35 |
1/1✓ Branch 1 taken 4 times.
|
4 | str.setValue(varNameCall); |
36 |
1/1✓ Branch 1 taken 4 times.
|
4 | str.setIsVarCall(true); |
37 |
2/2✓ Branch 1 taken 4 times.
✓ Branch 4 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 4 taken 8 times.
✓ Branch 5 taken 4 times.
|
12 | for(std::vector<PNestedStr>::const_iterator it(vecNestedStr.begin()); it != vecNestedStr.end(); ++it){ |
52 |
3/3✓ Branch 2 taken 8 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 4 times.
|
8 | if(it->getIsVarCall()){ |
53 |
5/5✓ Branch 2 taken 4 times.
✓ Branch 5 taken 4 times.
✓ Branch 8 taken 4 times.
✓ Branch 11 taken 4 times.
✓ Branch 14 taken 4 times.
|
4 | PMapKnownVar::const_iterator itCall(mapKeyVariable.find(varBegin + it->getValue() + varEnd)); |
54 |
2/2✓ Branch 2 taken 3 times.
✓ Branch 3 taken 1 times.
|
4 | if(itCall != mapKeyVariable.end()){ |
55 |
1/1✓ Branch 2 taken 3 times.
|
3 | out += itCall->second; |
56 | }else{ | ||
57 |
4/4✓ Branch 2 taken 1 times.
✓ Branch 5 taken 1 times.
✓ Branch 8 taken 1 times.
✓ Branch 11 taken 1 times.
|
1 | out += varBegin + it->getValue() + varEnd; |
58 | } | ||
59 | }else{ | ||
60 |
2/2✓ Branch 2 taken 4 times.
✓ Branch 5 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 |
7/7✓ Branch 1 taken 5 times.
✓ Branch 2 taken 2 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 4 times.
✓ Branch 9 taken 3 times.
|
7 | if(varBegin == "" || varEnd == ""){return baseStr;} |
74 |
1/1✓ Branch 1 taken 4 times.
|
4 | PNestedCall call; |
75 |
1/1✓ Branch 1 taken 4 times.
|
4 | dico_create_nested_call(call, baseStr, varBegin, varEnd); |
76 |
1/1✓ Branch 1 taken 4 times.
|
4 | PString out(""); |
77 |
1/1✓ Branch 1 taken 4 times.
|
4 | dico_replace_nested_call(out, call, mapKeyVariable, varBegin, varEnd); |
78 |
1/1✓ Branch 1 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 |