void FileBot::clearMemory(FileNode *fileNode)
{
bool lastNode = false;
// this case will happened only when the root is supply
if( fileList.size() == 0 || (fileList.begin())->sibling.empty() ) {
BOOST_LOG_TRIVIAL(info) << "current node has no sibling: " << endl;
return;
}
// if this is the only node in the container
// clean up the container and then bail
FileNode *firstNode = &*(fileList.begin());
// test on first node is empty
if( !firstNode->sibling.empty() && firstNode->sibling.size() == 0 ) {
BOOST_LOG_TRIVIAL(info) << "This is the only node. Root size [" << fileList.size() << "]";
fileList.erase_and_dispose(fileList.begin(), fileList.end(), DisposeFileNode());
return;
}
// if this is not the only node in the container
// clean up the container recursively
if( fileNode == NULL ) {
BOOST_LOG_TRIVIAL(info) << "current node has no sibling: " << fileNode;
fileNode = &*(fileList.begin());
fileList.erase_and_dispose(fileList.begin(), fileList.end(), DisposeFileNode());
lastNode = true;
}
else {
BOOST_LOG_TRIVIAL(info) << "current node has sibling: " << fileNode << " : " << fileNode->getName() << " sibling : " << fileNode->sibling.size();
if( fileNode->sibling.size() > 0 ) {
for( FileNodeListType::iterator it = fileNode->sibling.begin(); it != fileNode->sibling.end(); it++ ) {
clearMemory(&*(it));
}
}
else {
cout << fileNode << " has no more sibling." << endl;
return;
}
BOOST_LOG_TRIVIAL(info) << "cleaning sibling memory for this node: " << fileNode << " node name: " << fileNode->getName();
fileNode->sibling.erase_and_dispose(fileNode->sibling.begin(), fileNode->sibling.end(), DisposeFileNode());
}
if( lastNode ) {
BOOST_LOG_TRIVIAL(info) << "Reacing the root. Root size [" << fileList.size() << "]";
fileList.erase_and_dispose(fileList.begin(), fileList.end(), DisposeFileNode());
}
}
In the past few days I sat down just to review my test case, I found out some of the code was not covered by the test cases. Those uncover pieces are 16-20, 24-30, and 49-52. I was shocked when I see those uncovered pieces. I wonder whether those pieces are unused code since none of the test cases cover them up.I study the code carefully, test run for few times and finally I got a fantastic conclusion. There are 2 sections are required for this function to carry on its job; first section would be the validation, this will validate whether the container, as well as, the FileNode's sibling contain any elements in it? This is the one:
// this case will happened only when the root is supply
if( fileList.size() == 0 || (fileList.begin())->sibling.empty() ) {
BOOST_LOG_TRIVIAL(info) << "current node has no sibling: " << endl;
return;
}
Whereas the second section would be the core logic focus on cleaning the container, as well as, the sibling of each FileNode. Here is the one: BOOST_LOG_TRIVIAL(info) << "current node has sibling: " << fileNode << " : " << fileNode->getName() << " sibling : " << fileNode->sibling.size();
if( fileNode->sibling.size() > 0 ) {
for( FileNodeListType::iterator it = fileNode->sibling.begin(); it != fileNode->sibling.end(); it++ ) {
clearMemory(&*(it));
}
}
else {
cout << fileNode << " has no more sibling." << endl;
return;
}
BOOST_LOG_TRIVIAL(info) << "cleaning sibling memory for this node: " << fileNode << " node name: " << fileNode->getName();
fileNode->sibling.erase_and_dispose(fileNode->sibling.begin(), fileNode->sibling.end(), DisposeFileNode());
Now the code is much more readable. Don't you agree? Oh! by the way, I already moved this function into the destructor since I'll invoke this function at the end of each unit test. Don't you feel much better?FileBot::~FileBot()
{
clearMemory(&*(fileList.begin()));
}
