I know it seems I have a habit of answering my own questions, but so far I have been stuck on this one and need some help.
I have made some code to load a json formatted file into a class system. I put all the code up here: https://github.com/tomzooi/readreq
in short of what I am trying to do: first I created some code that can read in a "requirements" file and store it using the Requirement class from class.h This again I can output in human readable format to screen or store it in a json file. this works.
Then I want to be able to read in a JSON file and store it in memory using the same Requirement object again, this however is not working so well (so far).
The main issue now is the part where I am traversing the property tree, this is mainly done in this recursive function:
void display(const int depth, const boost::property_tree::ptree& tree, Requirement * cur_requirement, std::vector<Requirement> &requirements) {
unsigned int count;
std::string label,level,description;
boost::property_tree::ptree kids = tree.get_child("");
bool godown = false;
for (const auto& v : kids) { // v is of type ptree::value_type
std::cout << std::string("").assign(depth+1,'#') << " ";
std::string nodestr = tree.get<std::string>(v.first);
//std::cout << v.first << " = " << nodestr << std::endl;
if (v.first == "label") {
label = nodestr;
std::cout << "lbl: " << label << std::endl;
}
else if(v.first == "level") {
//std::cout << "LABEL!";
level = nodestr;
std::cout << "lvl: " << level << std::endl;
}
else if(v.first == "description") {
description = nodestr;
std::cout << "dsc: " << description << std::endl;
}
else if(v.first == "children") { //going down, store stuff first
if(depth == 0) { //zero depth
std::cout << "zero depth...";
requirements.emplace_back(level, description, label,cur_requirement);
cur_requirement = &requirements.back();
}
else { //one or higher depth
std::cout << "at depth " << depth << "..." << std::flush;
cur_requirement->children.emplace_back(level,description,label,cur_requirement->parent);
cur_requirement = &cur_requirement->children.back();
}
std::cout << "going down" << std::endl;
//cur_requirement = &cur_requirement->children.back();
display(depth+1, v.second, cur_requirement,requirements);
}
else if(v.first == "") {
std::cout << "empty v.first ... level: " << level << std::endl;
if(depth == 0) { //zero depth
std::cout << "store at zero depth...";
requirements.emplace_back(level, description, label,cur_requirement);
cur_requirement = &requirements.back();
}
else { //one or higher depth
std::cout << "store at depth " << depth << " : " << level << "--" << description << std::flush;
cur_requirement->children.emplace_back(level,description,label,cur_requirement->parent);
//cur_requirement = &cur_requirement->children.back();
}
std:: cout << " going to next " << std::endl;
//cur_requirement = &cur_requirement->children.back();
display(depth, v.second, cur_requirement,requirements);
}
else {
std:: cout << "what else..." << std::endl;
}
// v.first is the name of the child
// v.second is the child tree
}
};
The output I get currently is this:
[tom@tomtop dev]$ ./readreq The_system.F.req.json
name: The system prefix: F
# lvl: should
# dsc: very well performance wise
# lbl: goperf
# zero depth...going down
## empty v.first ... level:
store at depth 1 : -- going to next
## lvl: should
## dsc: be listening to spaces as well
## lbl: lisspace
## empty v.first ... level:
store at depth 1 : -- going to next
## lvl: will
## dsc: a lot of levels back down again
## at depth 1...going down
### empty v.first ... level:
store at depth 2 : -- going to next
### lvl: empty
### dsc: empty
### lbl: empty
### at depth 2...going down
#### empty v.first ... level:
store at depth 3 : -- going to next
#### lvl: can
#### dsc: skip all the way back here
#### lbl: skiphere
#### empty v.first ... level:
store at depth 3 : -- going to next
#### lvl: can
#### dsc: take three linestr
#### lbl: threelines
level: should description:very well performance wise label: goperf
level: description: label:
level: description: label:
level: will description:a lot of levels back down again label:
level: description: label:
level: empty description:empty label: empty
level: description: label:
level: description: label:
Most of which makes sense, and most of it seems to work, but there is one thing that puzzles me. The property tree is organized in such a way there is an "empty" node before each "child" and also inbetween the elements of arrays. (correct me if I'm wrong, i'm not that familiar with property tree).
So after I come upon a "children" or "" (empty) element I want to store the data I previously collected, stored in the variables level, description and label.
and here is the funny part, when the element is "children", this works like a charm, however, when the element is "", suddenly the variables are empty, even though the variables were not reinitialized, neither did I go deeper into the property tree, I only iterate to the next "kid" within the for loop.
So where I expect the output to be this:
## lvl: should
## dsc: be listening to spaces as well
## lbl: lisspace
## empty v.first ... level: should
store at depth 1 : should -- be listening to spaces as well going to next
the last line (generated by
std::cout << "empty v.first ... level: " << level << std::endl; std::cout << "store at depth " << depth << " : " << level << "--" << description << std::flush;
) shows this:
store at depth 1 : -- going to next
giving the impression that label, description and level where somehow empty, and nowhere is there an assignment which could make them empty.
So if anyone can explain this misterious behaviour to me I would be very glad.