GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: tmp_project/FileParser/src/dico_replace_var.cpp Lines: 107 107 100.0 %
Date: 2023-10-11 10:52:07 Branches: 148 150 98.7 %

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<std::string, 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 std::string & baseStr, const std::string & varBegin, const std::string & varEnd){
22
8
	PFileParser parser;
23
4
	parser.setFileContent(baseStr);
24
9
	while(!parser.isEndOfFile()){
25
10
		std::string prevCall(parser.getUntilKeyWithoutPatern(varBegin));
26
5
		if(prevCall != ""){
27
8
			PNestedStr str;
28
4
			str.setValue(prevCall);
29
4
			str.setIsVarCall(false);
30
4
			call.getVecNestedStr().push_back(str);
31
		}
32
10
		std::string varNameCall(parser.getUntilKeyWithoutPatern(varEnd));
33
5
		if(varNameCall != ""){
34
8
			PNestedStr str;
35
4
			str.setValue(varNameCall);
36
4
			str.setIsVarCall(true);
37
4
			call.getVecNestedStr().push_back(str);
38
		}
39
	}
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(std::string & out, const PNestedCall & call, const PMapKnownVar & mapKeyVariable, const std::string & varBegin, const std::string & varEnd){
50
4
	const std::vector<PNestedStr> & vecNestedStr = call.getVecNestedStr();
51
12
	for(std::vector<PNestedStr>::const_iterator it(vecNestedStr.begin()); it != vecNestedStr.end(); ++it){
52
8
		if(it->getIsVarCall()){
53

4
			PMapKnownVar::const_iterator itCall(mapKeyVariable.find(varBegin + it->getValue() + varEnd));
54
4
			if(itCall != mapKeyVariable.end()){
55
3
				out += itCall->second;
56
			}else{
57

1
				out += varBegin + it->getValue() + varEnd;
58
			}
59
		}else{
60
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
std::string dico_replace_var_str(const std::string & baseStr, const PMapKnownVar & mapKeyVariable, const std::string & varBegin, const std::string & varEnd){
73

7
	if(varBegin == "" || varEnd == ""){return baseStr;}
74
8
	PNestedCall call;
75
4
	dico_create_nested_call(call, baseStr, varBegin, varEnd);
76
8
	std::string out("");
77
4
	dico_replace_nested_call(out, call, mapKeyVariable, varBegin, varEnd);
78
4
	return out;
79
}
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
80
bool createNestedCallFromStr(PNestedCall & call, const std::string & value, const std::string varName, const std::string & varBegin, const std::string & varEnd){
90
80
	call.setName(varName);
91
80
	PFileParser parser;
92
80
	parser.setFileContent(value);
93
80
	bool hasNestedCall(false);
94
182
	while(!parser.isEndOfFile()){
95
204
		std::string prevCall(parser.getUntilKeyWithoutPatern(varBegin));
96
102
		if(prevCall != ""){
97
190
			PNestedStr str;
98
95
			str.setValue(prevCall);
99
95
			str.setIsVarCall(false);
100
95
			call.getVecNestedStr().push_back(str);
101
		}
102
204
		std::string varNameCall(parser.getUntilKeyWithoutPatern(varEnd));
103
102
		if(varNameCall != ""){
104
45
			PNestedStr str;
105
45
			str.setValue(varNameCall);
106
45
			str.setIsVarCall(true);
107
45
			call.getVecNestedStr().push_back(str);
108
45
			hasNestedCall = true;
109
		}
110
	}
111
160
	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 dico : DicoValue to be used
119
*/
120
124
void dico_find_all_var(PMapKnownVar & mapReadyVar, PVecReplaceVar & mapNestedVar, MapVarWithNestedCall & mapVarWithNestedCall, DicoValue & dico){
121
124
	if(dico.hasMap()){
122
28
		MapDicoValue & mapDico = dico.getMapChild();
123
132
		for(MapDicoValue::iterator it(mapDico.begin()); it != mapDico.end(); ++it){
124
104
			dico_find_all_var(mapReadyVar, mapNestedVar, mapVarWithNestedCall, it->second);
125
		}
126
96
	}else if(dico.hasVec()){
127
7
		VecDicoValue & vecDico = dico.getVecChild();
128
19
		for(VecDicoValue::iterator it(vecDico.begin()); it != vecDico.end(); ++it){
129
12
			dico_find_all_var(mapReadyVar, mapNestedVar, mapVarWithNestedCall, *it);
130
		}
131
89
	}else if(dico.hasKey()){	//No map, no vector but a key, this is a string variable
132
160
		std::string strValue(dico.getString()), varName(dico.getKey());
133
		//Let's check is the value contains nested calls
134
		//We will create a class to handle the split between string part and nested calls
135
160
		PNestedCall call;
136
		//We add the class in the proper map
137

80
		if((createNestedCallFromStr(call, strValue, varName, "${", "}"))){	//There is (at least) one nested call
138
29
			mapNestedVar.push_back(std::pair<PNestedCall, DicoValue*>(call, &dico));
139
29
			mapVarWithNestedCall[varName] = std::pair<PNestedCall, DicoValue*>(call, &dico);
140
		}else{								//There is no nested call
141
51
			mapReadyVar[varName] = strValue;
142
		}
143
	}
144
124
}
145
146
147
///Update variables with nested calls
148
/**	@param[out] mapReadyVar : map of variables with values only
149
 * 	@param[out] mapNestedVar : map of variables with nested calls
150
 * 	@param nestedCall : nested call which is the split value of the dico
151
 * 	@param mapVarWithNestedCall : map of the variables which use nested calls
152
 * 	@param dico : DicoValue to be used
153
*/
154
45
void dico_update_all_nestedCall(PMapKnownVar & mapReadyVar, PVecReplaceVar & mapNestedVar, MapVarWithNestedCall & mapVarWithNestedCall,
155
				PNestedCall & nestedCall, DicoValue * dico)
156
{
157
	//For each call, we check if it comes from the mapReadyVar, from the mapNestedVar or from nowhere
158
90
	std::string outputValue("");
159
45
	std::vector<PNestedStr> & vecNestedStr = nestedCall.getVecNestedStr();
160
189
	for(std::vector<PNestedStr>::iterator it(vecNestedStr.begin()); it != vecNestedStr.end(); ++it){
161
144
		if(!it->getIsVarCall()){	//If it is not a var call, we skip it
162
72
			outputValue += it->getValue();
163
72
			continue;
164
		}
165
144
		std::string varName(it->getValue());
166
		//If the var comes from mapNestedVar, we have to resolve this one first
167
72
		MapVarWithNestedCall::iterator itNested = mapVarWithNestedCall.find(varName);
168
72
		if(itNested != mapVarWithNestedCall.end()){
169
16
			dico_update_all_nestedCall(mapReadyVar, mapNestedVar, mapVarWithNestedCall, itNested->second.first, itNested->second.second);
170
16
			mapVarWithNestedCall.erase(varName);	//We solve varName, so we erase it from the mapNestedVar
171
			//But now, the varName entry does exist in the mapReadyVar
172
		}
173
		//If the var comes from mapReadyVar, we replace it
174
72
		PMapKnownVar::iterator itReady = mapReadyVar.find(varName);
175
72
		if(itReady != mapReadyVar.end()){
176
46
			outputValue += itReady->second;
177
		}else{
178
			//If we cannot find it, let's keep it unsolved (it can we a global variable)
179
26
			outputValue += "${" + varName + "}";
180
		}
181
	}
182
	//Finally, we can update the dico value, but we deal with the quotation
183
135
	std::string firstQuote(""), prevValue(dico->getValue());
184
45
	if(prevValue.size() != 0lu){
185
45
		if(prevValue.front() == '\''){firstQuote = "'";}
186
38
		else if(prevValue.front() == '"'){firstQuote = "\"";}
187
	}
188
45
	dico->setValue(firstQuote + outputValue + firstQuote);
189
190
	//And put its value into the mapReadyVar, because we solve it
191
45
	mapReadyVar[nestedCall.getName()] = outputValue;
192
45
}
193
194
///Update the variable which contains nested calls
195
/**	@param[out] mapReadyVar : map of variables with values only
196
 * 	@param[out] mapNestedVar : map of variables with nested calls
197
 * 	@param mapVarWithNestedCall : map of variable with nested call
198
*/
199
8
void dico_update_all_var(PMapKnownVar & mapReadyVar, PVecReplaceVar & mapNestedVar, MapVarWithNestedCall & mapVarWithNestedCall){
200
	//Let's try to complete the nested call
201
37
	for(PVecReplaceVar::iterator itNested(mapNestedVar.begin()); itNested != mapNestedVar.end(); ++itNested){
202
29
		PNestedCall & nestedCall = itNested->first;
203
29
		DicoValue * dico = itNested->second;
204
205
29
		dico_update_all_nestedCall(mapReadyVar, mapNestedVar, mapVarWithNestedCall, nestedCall, dico);
206
	}
207
8
}
208
209
///Replace all the variables which are string in the given DicoValue, when ${variable} apprears in the value
210
/**	@param dico : DicoValue to be updated
211
*/
212
8
void dico_replace_var(DicoValue & dico){
213
	//Let's find all the defined variables, linked to the DicoValue, string only
214
16
	PMapKnownVar mapReadyVar;
215
16
	PVecReplaceVar mapNestedVar;
216
16
	MapVarWithNestedCall mapVarWithNestedCall;
217
8
	dico_find_all_var(mapReadyVar, mapNestedVar, mapVarWithNestedCall, dico);
218
219
	//Update variables with nested call, separate those with nested call from the other
220
8
	dico_update_all_var(mapReadyVar, mapNestedVar, mapVarWithNestedCall);
221
8
}
222
223