When dealing with loading input configuration files, it is annoying to parse each line of the file and store the value in a parameter for each line. This often clutters the code due to the extensive if-else if-else if...-else statements for each config parameter. In the end this greatly affects the code maintainability. So let me introduce you a better approach to minimize the pain of maintenance.
Assumptions
I take it for granted that I'm addressing the audience who have their code in C++. I assume that you all might have stored the set of input parameters in a structure or a class, say ConfigStruct. If you haven't done so, I recommend encapsulating your input/output parameters in a nice structure atleast now. I use STL in this example to make things easier - you may also use your own version of the STL container if you are against using STL for some personal reasons.
Scenario: (existing parser logic)
If your input config parsing logic is something like,
if ( !strcmp(inputParam1,"paramStr1") ) {
load paramStr1's value into inputParam1
} else if ( !strcmp(inputParam2,"paramStr2") ) {
load paramStr2's value into inputParam2
} else {
print that the config parameter is unrecognized and probably quit
}
then you've come to the right place.
Pointer-based approach
This method deals with two forms of association:
a. Tying each config file tag to the datatype of corresponding variable - introduce a STL "map" called tagTypeMap
b. Tying each config file tag to the address of corresponding variable - introduce a STL "map" called tagAddrMap
Declaration of these maps
std::map<std::string,std::string> tagTypeMap;
std::map<std::string,void*> tagAddrMap;
New parser logic
registerConfig() {
#define REGISTER(tag,var) tagTypeMap[tag]=typeid(var).name();
REGISTER("paramStr1",inputParam1)
REGISTER("paramStr2",inputParam2)
//and so on.
#define REGISTER_ADDR(tag,var) tagAddrMap[tag]=(void*)&var;
REGISTER_ADDR("paramStr1",inputParam1)
REGISTER_ADDR("paramStr2",inputParam2)
//and so on.
}
parseTag() {
if ( tagTypeMap.find(tag) == tagTypeMap.end() )
return; //variable not found
std::string type = tagTypeMap.find(tag)->second;
if ( tagAddrMap.find(tag) == tagAddrMap.end() )
return; //addr not registered
void *vptr = tagAddrMap.find(tag)->second;
// If you include a new data type
// as input parameter, please define
// conversion for that data type in here
if ( type == typeid(std::string).name() ) {
std::string *ptr = (std::string*) vptr;
*ptr = value;
} else if ( type == typeid(int).name() ) {
int *ptr = (int*) vptr;
*ptr = atoi(value.c_str());
} else if ( type == typeid(float).name() ) {
float *ptr = (float*) vptr;
*ptr = atof(value.c_str());
} //and so on
}
I'll go over the second approach (template-based) in one of my future blogs (possibly the next one).
Until we meet again,
-Srini-

No comments:
Post a Comment