From 9f053e53e3275675e575683bda492b61b20c4797 Mon Sep 17 00:00:00 2001
From: Andrea Zoli <athlonz900@gmail.com>
Date: Thu, 19 Feb 2015 22:41:58 +0100
Subject: [PATCH] Fix xml parsing of SDFBlocks.

---
 src/ConfigurationFile.cpp |   1 -
 src/Field.cpp             |   4 +-
 src/InputPacketStream.cpp |   1 +
 src/Packet.cpp            |  46 --------
 src/PacketStream.cpp      |   8 +-
 src/SDFBlock.cpp          | 230 +++++++++++++++++++++-----------------
 6 files changed, 134 insertions(+), 156 deletions(-)

diff --git a/src/ConfigurationFile.cpp b/src/ConfigurationFile.cpp
index 692db65..6ee6872 100644
--- a/src/ConfigurationFile.cpp
+++ b/src/ConfigurationFile.cpp
@@ -87,7 +87,6 @@ char* ConfigurationFile::getLine() throw(PacketExceptionIO*)
 char* ConfigurationFile::getLine(const char* s) throw(PacketExceptionIO*)
 {
     char* line;
-
     try
     {
         line = this->getLine();
diff --git a/src/Field.cpp b/src/Field.cpp
index ad9af93..5d5f0c1 100644
--- a/src/Field.cpp
+++ b/src/Field.cpp
@@ -19,6 +19,8 @@
 #include "Field.h"
 #include "Utility.h"
 
+//#define DEBUG 1
+
 using namespace PacketLib;
 
 static FieldType** filedTypeList = 0;
@@ -92,7 +94,7 @@ Field::Field(std::string name, std::string typeStr, std::string dim, std::string
 		type->dimension = atoi(dim.c_str());
 		type->type = Field::typeStringToEnum[typeStr];
 #ifdef DEBUG
-		std::cout << "Adding field '" << name << "' at index " << i << ", " << type->dimension << " bits type " << typeStr << " (" << type->type << ")" << std::endl;
+		std::cout << "Adding field '" << name << "', " << type->dimension << " bits type " << typeStr << " (" << type->type << ")" << std::endl;
 #endif
 
         if(prVal.compare("none") != 0)
diff --git a/src/InputPacketStream.cpp b/src/InputPacketStream.cpp
index cbd202e..fd35c5d 100644
--- a/src/InputPacketStream.cpp
+++ b/src/InputPacketStream.cpp
@@ -20,6 +20,7 @@
 
 using namespace PacketLib;
 
+#undef DEBUG
 
 InputPacketStream::InputPacketStream() : PacketStream()
 {
diff --git a/src/Packet.cpp b/src/Packet.cpp
index 33bcd71..1632a85 100644
--- a/src/Packet.cpp
+++ b/src/Packet.cpp
@@ -64,52 +64,6 @@ Packet::~Packet()
     delete[] identifiers;
 }
 
-const std::string fixed32[] = { "uint32", "int32", "float" };
-const std::string fixed64[] = { "uint64", "int64", "double" };
-
-void cachePhysicalIndexes(pugi::xml_node node, std::map<pugi::xml_node, int>& physicalIndex)
-{
-	int index = 0;
-	for(pugi::xml_node_iterator it=node.begin(); it != node.end(); ++it)
-	{
-		if(string(it->name()).compare("field") != 0)
-			continue;
-
-		physicalIndex[*it] = index;
-
-		// if 32bits fields
-		string typeStr = it->attribute("type").value();
-		bool found = false;
-		for(unsigned int i=0; i<3; i++)
-		{
-			if(typeStr.compare(fixed32[i]) == 0)
-			{
-				index+=2;
-				found = true;
-				break;
-			}
-		}
-		if(found)
-			continue;
-
-		// if 64bits fields
-		for(unsigned int i=0; i<3; i++)
-		{
-			if(typeStr.compare(fixed64[i]) == 0)
-			{
-				index+=4;
-				found = true;
-				break;
-			}
-		}
-		if(found)
-			continue;
-
-		// else (<= 16bits fields)
-		index++;
-	}
-}
-
 void Packet::createPacketType(pugi::xml_document& doc, pugi::xml_node hNode, int plPhysicalIndex, int plSize, pugi::xml_node pNode, bool isprefix, word dimprefix, std::map<pugi::xml_node, int>& physicalIndex)
 {
 	name = pNode.attribute("name").value();
diff --git a/src/PacketStream.cpp b/src/PacketStream.cpp
index 89f2b29..d20987d 100644
--- a/src/PacketStream.cpp
+++ b/src/PacketStream.cpp
@@ -25,10 +25,6 @@
 
 using namespace PacketLib;
 
-
-
-
-
 PacketStream::PacketStream(string fileNameConfig)
 {
 	filenameConfig = realpath(fileNameConfig.c_str(), NULL);
@@ -158,7 +154,9 @@ void PacketStream::cachePhysicalIndexes(pugi::xml_node node, std::map<pugi::xml_
 	{
 		if(string(it->name()).compare("field") != 0)
 			continue;
-
+#ifdef DEBUG
+		std::cout << "Physical index of " << it->attribute("name").value() << " is " << index << std::endl;
+#endif
 		physicalIndex[*it] = index;
 
 		// if 32bits fields
diff --git a/src/SDFBlock.cpp b/src/SDFBlock.cpp
index ccde830..eb327b7 100644
--- a/src/SDFBlock.cpp
+++ b/src/SDFBlock.cpp
@@ -36,11 +36,17 @@ void SDFBlockType::loadType(pugi::xml_node node, const pugi::xml_document& doc,
 {
 	nblockmax = 0;
 
-	const char* popName = node.attribute("name").value();
+	std::string tmp;
+	if(strcmp(node.name(),"sourcedatafield") == 0)
+	{
+		tmp = std::string(node.parent().attribute("name").value()) + "_sdf";
+	}
+	else
+		tmp = node.attribute("name").value();
 
-	int dimline = strlen(popName);
-	name = (char*) new char[dimline+1];
-	strncpy(name, popName, dimline+1);
+	name = (char*) new char[tmp.size()+1];
+	strncpy(name, tmp.c_str(), tmp.size());
+	name[tmp.size()] = 0;
 
 	pugi::xml_node fNode = node.child("field");
 	if(fNode)
@@ -50,115 +56,123 @@ void SDFBlockType::loadType(pugi::xml_node node, const pugi::xml_document& doc,
 
 	variablePresent = false;
 	pugi::xpath_node_set rbNodeSet = node.select_nodes("rblock");
-	if(rbNodeSet.size() == 0)
+	if(rbNodeSet.size() == 0) 
+	{
+		numberOfRBlocks = 0;
+		rblockFilename = 0;
+		rBlockVariable = 0;
+		maxNumberOfBlock = 0;
+		indexOfNBlock = 0;
+		subFromNBlock = 0;
+		numberOfBlockFixed = 0;
+		headerLevelOfNBlockIndex = 0;
+		operatorType = 0;
+
+		return;
+	}
+	variablePresent = true;
+#ifdef DEBUG
+	std::cout << "fixed part: " << variablePresent;
+	std::cout << " variable part: " << variablePresent << std::endl;
+#endif
+	numberOfRBlocks = rbNodeSet.size();
+	if(numberOfRBlocks > 65535)
+		throw new PacketExceptionFileFormat("Too many number of Rblocks in the packet type.");
+	rblockFilename = new char*[numberOfRBlocks];
+	rBlockVariable = new bool[numberOfRBlocks];
+	maxNumberOfBlock = new word[numberOfRBlocks];
+	indexOfNBlock = new word[numberOfRBlocks];
+	subFromNBlock = new word[numberOfRBlocks];
+	numberOfBlockFixed = new bool[numberOfRBlocks];
+	headerLevelOfNBlockIndex = new word[numberOfRBlocks];
+	operatorType = new byte[numberOfRBlocks];
+
+	for(int i=0; i < numberOfRBlocks; i++)
 	{
-		variablePresent = true;
-		numberOfRBlocks = rbNodeSet.size();
-		if(numberOfRBlocks > 65535)
-			throw new PacketExceptionFileFormat("Too many number of Rblocks in the packet type.");
-		rblockFilename = new char*[numberOfRBlocks];
-		rBlockVariable = new bool[numberOfRBlocks];
-		maxNumberOfBlock = new word[numberOfRBlocks];
-		indexOfNBlock = new word[numberOfRBlocks];
-		subFromNBlock = new word[numberOfRBlocks];
-		numberOfBlockFixed = new bool[numberOfRBlocks];
-		headerLevelOfNBlockIndex = new word[numberOfRBlocks];
-		operatorType = new byte[numberOfRBlocks];
-
-		for(int i=0; i < numberOfRBlocks; i++)
+		const pugi::xml_node rbNode = rbNodeSet[i].node();
+		pugi::xml_attribute idref = rbNode.attribute("idref");
+		if(idref)
+			rBlockVariable[i] = true;
+		else
+			rBlockVariable[i] = false;
+
+		const char* nblocks = rbNode.attribute("maxnumberofblocks").value();
+		maxNumberOfBlock[i] = atoi(nblocks);
+		if(maxNumberOfBlock[i] > 65535)
+			throw new PacketExceptionFileFormat("Too many number of blocks in the packet type.");
+
+		if(!idref)
 		{
-			const pugi::xml_node rbNode = rbNodeSet[i].node();
-			pugi::xml_attribute idref = rbNode.attribute("idref");
-			if(idref)
-				rBlockVariable[i] = true;
-			else
-				rBlockVariable[i] = false;
-
-			const char* nblocks = rbNode.attribute("maxnumberofblocks").value();
-			maxNumberOfBlock[i] = atoi(nblocks);
-			if(maxNumberOfBlock[i] > 65535)
-				throw new PacketExceptionFileFormat("Too many number of blocks in the packet type.");
-
-			if(!idref)
-				headerLevelOfNBlockIndex[i] = 0;
-			else
-			{
-				string query = string("//field[@id=\"")+idref.value()+"\"]";
-				pugi::xml_node numberofblocksid = doc.select_nodes(query.c_str())[0].node();
-				pugi::xml_node nodetmp = rbNode;
-				unsigned int level = 0;
+			stringstream ss;
+			ss << "idref attribute not defined for rblock" << rbNode.attribute("name").value();
+			throw new PacketExceptionFileFormat(ss.str().c_str());
+		}
+
+		string query = string("//field[@id=\"")+idref.value()+"\"]";
+		pugi::xml_node numberofblocksid = doc.select_nodes(query.c_str())[0].node();
+		pugi::xml_node nodetmp = rbNode;
+		unsigned int level = 0;
 
-				while(nodetmp.parent() != numberofblocksid.parent())
+		while(nodetmp.parent() != numberofblocksid.parent())
+		{
+			// if the parent is a packet means that the id is not in the fixed part of the
+			// recursive rblocks nor the sourcedatafield. So test the datafieldheader
+			// and header, otherwise complain.
+			if(string(nodetmp.parent().name()).compare("packet") == 0)
+			{
+				string idparentnodename = numberofblocksid.parent().name();
+				if(idparentnodename.compare("datafieldheader") == 0)
+				{
+					// we have already add 1 level because nodetmp in this case is
+					// the sourcedatafield node
+				}
+				else if(idparentnodename.compare("header") == 0)
 				{
-					// if the parent is a packet means that the id is not in the fixed part of the
-					// recursive rblocks nor the sourcedatafield. So test the datafieldheader
-					// and header, otherwise complain.
-					if(string(nodetmp.parent().name()).compare("packet") == 0)
-					{
-						string idparentnodename = numberofblocksid.parent().name();
-						if(idparentnodename.compare("datafieldheader") == 0)
-						{
-							// we have already add 1 level because nodetmp in this case is
-							// the sourcedatafield node
-						}
-						else if(idparentnodename.compare("header") == 0)
-						{
-							// we add just one level for the same reason above
-							level++;
-						}
-						else
-						{
-							std::stringstream ss;
-							ss << "Error on id association. Id'" << idref.value() << "' doesn't exists. idref defined by rblock '" << rbNode.attribute("name").value() << "'.";
-							throw new PacketExceptionFileFormat(ss.str().c_str());
-						}
-
-						break;
-					}
+					// we add just one level for the same reason above
 					level++;
-					nodetmp = nodetmp.parent();
 				}
-				headerLevelOfNBlockIndex[i] = level;
-				indexOfNBlock[i] = physicalIndex[numberofblocksid]; // TODO fix this..
-				pugi::xml_attribute offsetAttr = numberofblocksid.attribute("numberofblocksoffset");
-				const char* offset;
-				if(offsetAttr)
-					offset = offsetAttr.value();
 				else
-					offset = "0";
-
-				switch(offset[0])
 				{
-					case '/':
-						operatorType[i] = 1;
-						subFromNBlock[i] = atoi(offset+1);
-						break;
-					case '*':
-						operatorType[i] = 2;
-						subFromNBlock[i] = atoi(offset+1);
-						break;
-					default:
-						operatorType[i] = 0;
-						subFromNBlock[i] = atoi(offset);
+					std::stringstream ss;
+					ss << "Error on id association. Id'" << idref.value() << "' doesn't exists. idref defined by rblock '" << rbNode.attribute("name").value() << "'.";
+					throw new PacketExceptionFileFormat(ss.str().c_str());
 				}
 
-				rblockFilename[i] = (char*) rbNode.attribute("name").value();
+				break;
 			}
+			level++;
+			nodetmp = nodetmp.parent();
+		}
+		headerLevelOfNBlockIndex[i] = level;
+		indexOfNBlock[i] = physicalIndex[numberofblocksid];
+		pugi::xml_attribute offsetAttr = numberofblocksid.attribute("numberofblocksoffset");
+		const char* offset;
+		if(offsetAttr)
+			offset = offsetAttr.value();
+		else
+			offset = "0";
 
-			nblockmax += maxNumberOfBlock[i];
+		switch(offset[0])
+		{
+			case '/':
+				operatorType[i] = 1;
+				subFromNBlock[i] = atoi(offset+1);
+				break;
+			case '*':
+				operatorType[i] = 2;
+				subFromNBlock[i] = atoi(offset+1);
+				break;
+			default:
+				operatorType[i] = 0;
+				subFromNBlock[i] = atoi(offset);
 		}
-	}
-	else
-	{
-		numberOfRBlocks = 0;
-		rblockFilename = 0;
-		rBlockVariable = 0;
-		maxNumberOfBlock = 0;
-		indexOfNBlock = 0;
-		subFromNBlock = 0;
-		numberOfBlockFixed = 0;
-		headerLevelOfNBlockIndex = 0;
-		operatorType = 0;
+#ifdef DEBUG
+		std::cout << "Add rblock index for " << rbNode.attribute("name").value();
+		std::cout << " level " << level << " phyindex " << indexOfNBlock[i] << " offset " << offset << std::endl;
+#endif
+		rblockFilename[i] = (char*) rbNode.attribute("name").value();
+
+		nblockmax += maxNumberOfBlock[i];
 	}
 }
 
@@ -367,7 +381,18 @@ SDFBlock::~SDFBlock()
 void SDFBlock::loadFieldsSDFB(pugi::xml_node rbNode, const pugi::xml_document& doc,
                             std::map<pugi::xml_node, int>& physicalIndex)
 {
-	popName = (char*) rbNode.attribute("name").value();
+	std::string tmp;
+	if(strcmp(rbNode.name(),"sourcedatafield") == 0)
+	{
+		tmp = std::string(rbNode.parent().attribute("name").value()) + "_sdf";
+	}
+	else
+		tmp = rbNode.attribute("name").value();
+
+	popName = (char*) new char[tmp.size()+1];
+	strncpy(popName, tmp.c_str(), tmp.size());
+	popName[tmp.size()] = 0;
+
 	dword indexlist = 0;
 	type = 0;
 	while(blockTypeList[indexlist] != 0)
@@ -384,7 +409,6 @@ void SDFBlock::loadFieldsSDFB(pugi::xml_node rbNode, const pugi::xml_document& d
 	this->previous = previous;
 	if(type == 0)
 	{
-//     	cout << "create the type " << popName << endl;
 		type = new SDFBlockType;
 		blockTypeList[indexlist] = type;
 		type->loadType(rbNode, doc, physicalIndex);
@@ -423,7 +447,7 @@ void SDFBlock::loadFieldsSDFB(pugi::xml_node rbNode, const pugi::xml_document& d
 			block[nblock].setPreviousPop(&fixed);
 			block[nblock].setRBlockType(indexRBlock);
 			block[nblock].setID(id);
-			pugi::xml_node childNode = rbNode.child(type->rblockFilename[indexRBlock]);
+			pugi::xml_node childNode = rbNode.find_child_by_attribute("name", type->rblockFilename[indexRBlock]);
 			block[nblock].loadFieldsSDFB(childNode, doc, physicalIndex);
 			id++;
 		}
-- 
GitLab