diff --git a/include/Field.h b/include/Field.h index 1cbe96ca9a3c4d058898d8f78636b67efc1f8d7f..79b4ef8199684497b8f61fb137baaacfb1df052f 100644 --- a/include/Field.h +++ b/include/Field.h @@ -19,6 +19,7 @@ #define _FIELD_H_H #include "PacketLibDefinition.h" +#include <string> namespace PacketLib { @@ -42,7 +43,7 @@ public: int predefinedValue; /// Name of the field. - char* name; + std::string name; /// Logical type - NOT USED FOR NOW enum LogicalFieldDataType type; @@ -56,7 +57,7 @@ class Field public: /// Constructor of class. - Field(char* name, char* dimension, char* predefinedValue, int progressiv); + Field(std::string name, std::string dimension, std::string predefinedValue, int progressiv); /// Destructor of class. ~Field(); @@ -83,11 +84,17 @@ public: }; /// Name of the field. - inline char* getName() + std::string getName() { - return type->name; + return type->name.c_str(); }; + /// Return the logical field data type. + LogicalFieldDataType getType() + { + return type->type; + } + inline int getProgressiv() { return progressiv; diff --git a/include/Packet.h b/include/Packet.h index be75e4563d56857a55c81fa005c5d59547387ff5..973ba0790a66448681478cb42e0329e14279749b 100644 --- a/include/Packet.h +++ b/include/Packet.h @@ -55,6 +55,8 @@ public: /// Distruttore virtual ~Packet(); + void 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); + virtual bool createPacketType(char* fileName, bool prefix, word dimprefix) throw (PacketException*); /// Decode the packet @@ -174,16 +176,16 @@ public: ByteStreamPtr getOutputStream(); /// Gets the name of packet. - virtual char* getName() + virtual const char* getName() { - return name; + return (char*) name.c_str(); } /// The name of the file .packet that contains the structure of the packet - virtual char* getFileName() + virtual const char* getFileName() { - return filename; + return filename.c_str(); } @@ -289,7 +291,7 @@ protected: byte packetID; /// The name of the packet - char* name; + std::string name; /// List of identifiers. This identifiers permits to identify if the stream contains /// a particular type of packet @@ -319,7 +321,7 @@ protected: bool thereisprefix; /// The name of the file .packet that contains the structure of the packet - char* filename; + std::string filename; private: diff --git a/include/PacketBufferQ.h b/include/PacketBufferQ.h index c44621c065d6134f57e9b04886acc979c66e8fdf..34f70b4a0c7c8ac1cea08dea3044f98027dab442 100644 --- a/include/PacketBufferQ.h +++ b/include/PacketBufferQ.h @@ -28,7 +28,7 @@ namespace PacketLib { class PacketBufferQ { public: - PacketBufferQ(const string& configFile, const string& inputFile); + PacketBufferQ(string configFile, string inputFile); ~PacketBufferQ(); diff --git a/include/PacketBufferV.h b/include/PacketBufferV.h index 44ba49328e13bf47ee0f3dc6fe30ecf313a45e3f..4ba72f33bacb01c184ee47c842e37f49d89a29d2 100644 --- a/include/PacketBufferV.h +++ b/include/PacketBufferV.h @@ -30,7 +30,7 @@ class PacketBufferV { public: - PacketBufferV(const string& configFile, const string& inputFile); + PacketBufferV(string configFile, string inputFile); ~PacketBufferV(); diff --git a/include/PacketHeader.h b/include/PacketHeader.h index fb39368da94f4e890a948410f8d5005900942950..b5aaf50791f9711cc31f1dbd1818420e2e60ceef 100644 --- a/include/PacketHeader.h +++ b/include/PacketHeader.h @@ -39,6 +39,8 @@ public: name = n; }; + void loadHeader(pugi::xml_node hNode, int plPhysicalIndex, int plSize); + /// Loads data header from configuration file. bool loadHeader(char* fileName) throw(PacketException*); diff --git a/include/PacketNotRecognized.h b/include/PacketNotRecognized.h index 75e14d2f01ec01b520c8120e1a6e2341ff5c5383..6f599eb0f558c470df73bf914ca9657cbae2fec8 100644 --- a/include/PacketNotRecognized.h +++ b/include/PacketNotRecognized.h @@ -20,6 +20,7 @@ #include "Packet.h" #include "PacketLibDefinition.h" +#include "pugixml.h" namespace PacketLib { @@ -33,6 +34,8 @@ public: virtual ~PacketNotRecognized(); + void createPacketType(pugi::xml_node node, int plPhysicalIndex, int plSize); + virtual bool createPacketType(char* fileName, bool prefix, word dimprefix) throw (PacketException*); virtual bool setPacketValue(ByteStreamPtr prefix, ByteStreamPtr packetHeader, ByteStreamPtr packetDataField, int decodeType); diff --git a/include/PacketStream.h b/include/PacketStream.h index 4749ddb429e8fa7dbdb02aecc7b3efba98de8934..1ab3df6500b4767ba93d899dedb3592993577691 100644 --- a/include/PacketStream.h +++ b/include/PacketStream.h @@ -31,7 +31,7 @@ class PacketStream { public: - PacketStream(const char* fileNameConfig) ; + PacketStream(string fileNameConfig); PacketStream(); @@ -66,6 +66,8 @@ public: void setFileNameConfig(const char* f); + void createStreamStructureXml(); + /// This method creates the structure of the stream. /// The structure of the stream is represented with the pachetReference and the collection of type of packet. /// Each packet has the collection of field and the collection of identifier @@ -96,7 +98,7 @@ public: PacketHeader* headerReference; - char* filenameConfig; + string filenameConfig; char* pathFileNameConfig; @@ -120,6 +122,10 @@ protected: /// The dimension of the header word dimHeader; +private: + + void cachePhysicalIndexes(pugi::xml_node node, std::map<pugi::xml_node, int>& physicalIndex); + }; } diff --git a/include/PartOfPacket.h b/include/PartOfPacket.h index 3841c4a35bc42a71b1da12b7625b9c2f3d38d84c..27f6423384746c6afcffbb54d5f2c1e614b9a648 100644 --- a/include/PartOfPacket.h +++ b/include/PartOfPacket.h @@ -18,6 +18,7 @@ #ifndef _PARTOFPACKET_H #define _PARTOFPACKET_H +#include "pugixml.h" #include "InputText.h" #include "Field.h" #include "PacketLibDefinition.h" @@ -39,11 +40,13 @@ class PartOfPacket public: /// Constructor - PartOfPacket(const char* popName = 0); + PartOfPacket(const char* popName = ""); /// Virtual destructor virtual ~PartOfPacket(); + virtual void loadFields(pugi::xml_node node); + /// This method loads the field present into the InputText (passed with the /// parameter). /// The InputText must be open and the internal pointer of the file must @@ -67,6 +70,14 @@ public: return 0; }; + /// Returns a field in the list of fields of this part of packet. + /// \param fieldname Represent the name of the field. + virtual Field* getField(string fieldname) { + decode(); + word index = getFieldIndex(fieldname); + return fields[index]; + } + /// Returns the value of a field in the list of fields of this part of packet. /// The value returned is interpreted as a unsigned integer of less of equal 16 bits dimension /// (depends by the size of the field in bits) diff --git a/include/SDFBlock.h b/include/SDFBlock.h index 6a8315237cffddc014c1cab17e6b9d795a714ccd..ea547e33a2237fddd83fd58c702bd938df982a71 100644 --- a/include/SDFBlock.h +++ b/include/SDFBlock.h @@ -19,7 +19,9 @@ #define _SDFBlock_H #include "PacketException.h" #include "PartOfPacket.h" +#include "pugixml.h" #include <string> +#include <map> namespace PacketLib { @@ -32,6 +34,9 @@ public: SDFBlockType(); + void loadType(pugi::xml_node node, const pugi::xml_document& doc, + std::map<pugi::xml_node, int>& physicalIndex); + bool loadType(InputText& fp) throw(PacketException*); /// the name of the InputFile @@ -98,6 +103,9 @@ public: SDFBlock(); virtual ~SDFBlock(); + void loadFields(pugi::xml_node node, const pugi::xml_document& doc, + std::map<pugi::xml_node, int>& physicalIndex); + virtual bool loadFields(InputText& fp) throw(PacketException*); virtual void setPreviousPop(PartOfPacket* pop) diff --git a/include/SourceDataField.h b/include/SourceDataField.h index 432784a0974409ed65b7c9df44167530982e7099..729daa274affcbc481f4d034374b3771769b8f02 100644 --- a/include/SourceDataField.h +++ b/include/SourceDataField.h @@ -20,6 +20,7 @@ #include "PacketException.h" #include "PacketExceptionFileFormat.h" #include "SDFBlock.h" +#include "pugixml.h" namespace PacketLib { @@ -33,6 +34,8 @@ public: virtual ~SourceDataField(); + virtual void loadFields(pugi::xml_node node, const pugi::xml_document& doc, std::map<pugi::xml_node, int>& physicalIndex); + virtual bool loadFields(InputText& fp) throw(PacketException*); /// Get a block of number nblock of the group of blocks of the rblock with the index rBlockIndex. diff --git a/src/Field.cpp b/src/Field.cpp index 59bfa06dc7f9e86b87c992d01580adc803101315..ed9bffc3c6e6baec2d08d78913d6056883054292 100644 --- a/src/Field.cpp +++ b/src/Field.cpp @@ -23,25 +23,21 @@ using namespace PacketLib; static FieldType** filedTypeList = 0; - -Field::Field(char* n, char* dim, char* prVal, int count) : progressiv(count) +Field::Field(std::string n, std::string dim, std::string prVal, int count) : progressiv(count) { value = 0; /// create FieldType list if(filedTypeList == 0) { - //cout << "create list" << endl; dword nb = CONFIG_MAXNUMBEROFLINES_OFCONFIGILES/3; filedTypeList = (FieldType**) new FieldType* [nb]; for(dword i = 0; i<nb; i++) filedTypeList[i] = 0; } - //cout << "------" << endl; int i = 0; type = 0; while(filedTypeList[i] != 0) { - //cout << filedTypeList[i]->name << " " << n << endl; if(filedTypeList[i]->name == n) { type = filedTypeList[i]; @@ -50,16 +46,17 @@ Field::Field(char* n, char* dim, char* prVal, int count) : progressiv(count) else i++; } - //cout << type << endl; if(type == 0) { type = new FieldType; filedTypeList[i] = type; - type->name = n; + type->dimension = atoi(dim.c_str()); +#ifdef DEBUG + std::cout << "Adding field '" << n << "' at index " << i << ", " << type->dimension << " bits" << std::endl; +#endif - type->dimension = atoi(dim); - if(strcmp(prVal, "none") != 0) + if(prVal.compare("none") != 0) { type->thereIsPredefinedValue = true; type->predefinedValue = Utility::convertToInteger(prVal); diff --git a/src/Packet.cpp b/src/Packet.cpp index 1f1db9f2c3c9bc7b1e4cf8ab44b945ed53409a72..3b4eae22219c42128729be305c3642fafea6462e 100644 --- a/src/Packet.cpp +++ b/src/Packet.cpp @@ -15,7 +15,9 @@ * For commercial purpose see appropriate license terms * * * ***************************************************************************/ - +#include <map> +#include <sstream> +#include "pugixml.h" #include "Packet.h" #include "Field.h" #include "PacketLibDemo.h" @@ -25,9 +27,9 @@ using namespace PacketLib; #define DECODETYPE 2 Packet::Packet(bool bigendian) - : packetID(0), name(0), identifiers(0), + : packetID(0), name(""), identifiers(0), number_of_identifier(0), bigendian(bigendian), thereisprefix(false), - filename(0), first_output_stream_setted(false), dimPrefix(0), + filename(""), first_output_stream_setted(false), dimPrefix(0), dimPacketHeader(0), dimPacketDataFieldHeader(0), dimPacketSourceDataFieldFixed(0), dimPacketTail(0), dimPacketStartingFixedPart(0), decodedPacketHeader(false), @@ -43,6 +45,9 @@ Packet::Packet(bool bigendian) tempDataFieldHeader = ByteStreamPtr(new ByteStream); tempPacketDataField = ByteStreamPtr(new ByteStream); tempTail = ByteStreamPtr(new ByteStream); + + for(unsigned int i=0; i<3; i++) + type_of_identifier[i] = false; } @@ -59,6 +64,161 @@ 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(); + filename = name; + + // load the header + header->loadHeader(hNode, plPhysicalIndex, plSize); + dimPacketHeader = header->size(); + + // load the packet data field header + pugi::xml_node dfhNode = pNode.child("datafieldheader"); + if(!dfhNode) throw new PacketExceptionFileFormat("<datafieldheader> not found."); + PacketLib::DataFieldHeader* dfh = dataField->getPacketDataFieldHeader(); + dfh->loadFields(dfhNode); + dimPacketDataFieldHeader = dfh->size(); + + // load the packet source data field + pugi::xml_node sdfNode = pNode.child("sourcedatafield"); + if(!sdfNode) throw new PacketExceptionFileFormat("<sourcedatafield> not found."); + PacketLib::SourceDataField* sdf = new PacketLib::SourceDataField(dfh); + dataField->setPacketSourceDataField(sdf); + sdf->loadFields(sdfNode, doc, physicalIndex); + dimPacketSourceDataFieldFixed = sdf->sizeFixedPart(); + dimPacketStartingFixedPart = dimPacketHeader + dimPacketDataFieldHeader + dimPacketSourceDataFieldFixed; + + // load the identifiers + pugi::xpath_node_set idNodeSet = pNode.select_nodes("identifiers/identifier"); + if(idNodeSet.size() == 0) throw new PacketExceptionFileFormat("<identifier> not found."); + number_of_identifier = idNodeSet.size(); + identifiers = new PacketIdentifier* [number_of_identifier]; + type_of_identifier[0] = type_of_identifier[1] = type_of_identifier[2] = false; + unsigned int i = 0; + for(pugi::xpath_node_set::const_iterator it = idNodeSet.begin(); it != idNodeSet.end(); ++it) + { + pugi::xml_node identifier = it->node(); + string query = string("//field[@id=\"")+identifier.attribute("idref").value()+"\"]"; + pugi::xml_node fieldid = doc.select_nodes(query.c_str())[0].node(); + int nf = physicalIndex[fieldid]; + string parentName = fieldid.parent().name(); + byte type = -1; + if(parentName.compare("header") == 0) + type = 0; + else if(parentName.compare("datafieldheader") == 0) + type = 1; + else if(parentName.compare("sourcedatafield") == 0) + type = 2; + word v = Utility::convertToInteger(identifier.attribute("value").value()); + type_of_identifier[type] = true; + PacketIdentifier* p = new PacketIdentifier(nf, type, v); + identifiers[i] = p; + i++; + } + + // load the tail + pugi::xml_node tNode = pNode.child("tail"); + if(tNode) + { + PartOfPacket* tail = dataField->getPacketTail(); + tail->loadFields(tNode); + dimPacketTail = dataField->getPacketTail()->size(); + } + + // query for compression algorithm / compression level + pugi::xpath_node_set compression_algorithm = hNode.select_nodes("field[@id=\"packetlib:compression_algorithm\"]"); + pugi::xpath_node_set compression_level = hNode.select_nodes("field[@id=\"packetlib:compression_level\"]"); + + // load compression informations + // if not defined in the header find in datafieldheader + int algindex = 0; + if(compression_algorithm.empty()) + { + compression_algorithm = dfhNode.select_nodes("field[@id=\"packetlib:compression_algorithm\"]"); + algindex = 1; + } + // and sourcedatafield + if(compression_algorithm.empty()) + { + algindex = 2; + compression_algorithm = sdfNode.select_nodes("@field[id=\"packetlib:compression_algorithm\"]"); + } + + // if not defined in the header find in datafieldheader + int lvlindex = 0; + if(compression_level.empty()) + { + compression_level = dfhNode.select_nodes("field[@id=\"packetlib:compression_level\"]"); + lvlindex = 1; + } + // and sourcedatafield + if(compression_level.empty()) + { + lvlindex = 2; + compression_level = sdfNode.select_nodes("@field[id=\"packetlib:compression_level\"]"); + } + + if(!compression_algorithm.empty() && !compression_level.empty()) + { + compressible = true; + compressionAlgorithmsIndex = physicalIndex[compression_algorithm[0].node()]; + compressionAlgorithmsSection = algindex; + compressionLevelIndex = physicalIndex[compression_level[0].node()]; + compressionLevelSection = lvlindex; + } + + // allocate the output stream + dword dimpo = sizeMax(); + dword dimpr = (isprefix?dimprefix:0); + packet_output = ByteStreamPtr(new ByteStream(dimpo + dimpr, bigendian)); +} bool Packet::createPacketType(char* fileName, bool isprefix, word dimprefix) throw (PacketException*) diff --git a/src/PacketBufferQ.cpp b/src/PacketBufferQ.cpp index d7dc4a680eebcb171b142f3c91dca96a29a7b8fd..7e8bb0110ae7d9d09749747a53c500247fb8dfdf 100644 --- a/src/PacketBufferQ.cpp +++ b/src/PacketBufferQ.cpp @@ -20,13 +20,13 @@ namespace PacketLib { -PacketBufferQ::PacketBufferQ(const string& configFile, const string& inputFile) +PacketBufferQ::PacketBufferQ(string configFile, string inputFile) { - _ips = new InputPacketStream(configFile.c_str()); + _ips = new InputPacketStream(realpath(configFile.c_str(), NULL)); _ips->createStreamStructure(); _in = (Input*) new InputFile(_ips->isBigEndian()); char** param = new char*[2]; - param[0] = (char*) inputFile.c_str(); + param[0] = (char*) realpath(inputFile.c_str(), NULL); param[1] = 0; _in->open(param); _ips->setInput(_in); diff --git a/src/PacketBufferV.cpp b/src/PacketBufferV.cpp index 152ccb223e6e3c010d230e5bf2f42091223ea85e..33d4a2056667802eca8befa75bb15640153af5a4 100644 --- a/src/PacketBufferV.cpp +++ b/src/PacketBufferV.cpp @@ -19,14 +19,14 @@ namespace PacketLib { -PacketBufferV::PacketBufferV(const string& configFile, const string& inputFile) +PacketBufferV::PacketBufferV(string configFile, string inputFile) : currentIndex(0), currentIndexBS(0) { - _ips = new InputPacketStream(configFile.c_str()); + _ips = new InputPacketStream(realpath(configFile.c_str(), NULL)); _ips->createStreamStructure(); _in = (Input*) new InputFile(_ips->isBigEndian()); char** param = (char**) new char*[2]; - param[0] = (char*) inputFile.c_str(); + param[0] = (char*) realpath(inputFile.c_str(), NULL); param[1] = 0; _in->open(param); _ips->setInput(_in); diff --git a/src/PacketHeader.cpp b/src/PacketHeader.cpp index f08e0947f7e8d92c43d02cac01198e596233dcaf..65f2f9263e52abc60ef9f917fe8945e580d81738 100644 --- a/src/PacketHeader.cpp +++ b/src/PacketHeader.cpp @@ -20,8 +20,6 @@ using namespace PacketLib; - - PacketHeader::PacketHeader() : PartOfPacket("Packet Header") { name = 0; @@ -34,7 +32,15 @@ PacketHeader::~PacketHeader() } +void PacketHeader::loadHeader(pugi::xml_node hNode, int plPhysicalIndex, int plSize) +{ + name = new char[100]; + name = strncpy(name, hNode.attribute("name").value(), 100); + numberOfFieldWithPacketDimension = plPhysicalIndex; + dimensionOfPacketLength = plSize; + loadFields(hNode); +} bool PacketHeader::loadHeader(char* fileName) throw(PacketException*) { diff --git a/src/PacketNotRecognized.cpp b/src/PacketNotRecognized.cpp index b9ae8fdf7c07d04b685228fad1036c3dffae0156..6662f568200bf2c9594dca00aee2e1b06634998b 100644 --- a/src/PacketNotRecognized.cpp +++ b/src/PacketNotRecognized.cpp @@ -20,35 +20,20 @@ using namespace PacketLib; +void PacketNotRecognized::createPacketType(pugi::xml_node node, int plPhysicalIndex, int plSize) +{ + packetID = 0; + header->loadHeader(node, plPhysicalIndex, plSize); + name = "Packet not Recognized\0"; +} + bool PacketNotRecognized::createPacketType(char* fileName, bool prefix, word dimprefix) throw (PacketException*) { packetID = 0; if(header->loadHeader(fileName)) { - name = new char [22]; - name[0] = 'P'; - name[1] = 'a'; - name[2] = 'c'; - name[3] = 'k'; - name[4] = 'e'; - name[5] = 't'; - name[6] = ' '; - name[7] = 'n'; - name[8] = 'o'; - name[9] = 't'; - name[10] = ' '; - name[11] = 'R'; - name[12] = 'e'; - name[13] = 'c'; - name[14] = 'o'; - name[15] = 'g'; - name[16] = 'n'; - name[17] = 'i'; - name[18] = 'z'; - name[19] = 'e'; - name[20] = 'd'; - name[21] = '\0'; + name = "Packet not Recognized\0"; return true; } else diff --git a/src/PacketStream.cpp b/src/PacketStream.cpp index 9c31980b3e9c74fca542fb9ccbe6f13e8a16aebd..89f2b298241d43606178827983c723868a82cf88 100644 --- a/src/PacketStream.cpp +++ b/src/PacketStream.cpp @@ -21,6 +21,7 @@ #include "PacketExceptionIO.h" #include "PacketNotRecognized.h" #include "PacketLibDemo.h" +#include <sstream> using namespace PacketLib; @@ -28,9 +29,9 @@ using namespace PacketLib; -PacketStream::PacketStream(const char* fileNameConfig) +PacketStream::PacketStream(string fileNameConfig) { - this->filenameConfig = (char*) fileNameConfig; + filenameConfig = realpath(fileNameConfig.c_str(), NULL); numberOfPacketType = 0; headerReference = 0; //TODO @@ -39,14 +40,14 @@ PacketStream::PacketStream(const char* fileNameConfig) memset(packetType, 0, sizeof(Packet*)*255); pathFileNameConfig = 0; dimHeader = 0; + std::cout << "Loading config file " << filenameConfig << " ..." << std::endl; createStreamStructure(); + std::cout << "Load complete." << std::endl; } - - PacketStream::PacketStream() + : filenameConfig("") { - this->filenameConfig = 0; numberOfPacketType = 0; headerReference = 0; //TODO @@ -147,14 +148,153 @@ Packet* PacketStream::getPacket(ByteStreamPtr stream) throw(PacketException*){ } +const std::string fixed32[] = { "uint32", "int32", "float" }; +const std::string fixed64[] = { "uint64", "int64", "double" }; + +void PacketStream::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 PacketStream::createStreamStructureXml() +{ + std::map<pugi::xml_node, int> physicalIndex; + + pugi::xml_document doc; + + // open the config file + if (!doc.load_file(filenameConfig.c_str())) + { + std::stringstream ss; + ss << "Cannot open " << filenameConfig; + throw new PacketExceptionFileFormat(ss.str().c_str()); + } + // cache all the field physical indexes + pugi::xpath_node_set fieldParents = doc.select_nodes("//*[field]"); + for(pugi::xpath_node_set::const_iterator it = fieldParents.begin(); it != fieldParents.end(); ++it) + cachePhysicalIndexes(it->node(), physicalIndex); + + // get the stream node + pugi::xml_node sNode = doc.child("stream"); + if(!sNode) throw new PacketExceptionFileFormat("<stream> not found."); + + if(pathFileNameConfig) free(pathFileNameConfig); + pathFileNameConfig = getcwd(NULL, 512L); + + bigendian = false; + pugi::xml_attribute beAttr = sNode.attribute("bigendian"); + if(beAttr && strcmp(beAttr.value(), "true") == 0) + bigendian = true; +#ifdef DEBUG + std::cout << "big endian? " << beAttr.value() << std::endl; +#endif + + dimPrefix = 0; + prefix = false; + pugi::xml_attribute preAttr = sNode.attribute("prefixSize"); + if(preAttr) + { + prefix = true; + dimPrefix = atoi(preAttr.value()); + } +#ifdef DEBUG + std::cout << "prefix size: " << dimPrefix << std::endl; +#endif + + // get the header node + pugi::xml_node hNode = sNode.child("header"); + if(!hNode) throw new PacketExceptionFileFormat("<header> not found."); + + // get the packet length physical index + std::string query = std::string("//field[@id=\"") + hNode.attribute("idref").value()+"\"]"; + pugi::xml_node plNode = hNode.select_nodes(query.c_str())[0].node(); + int plIndex = physicalIndex[plNode]; + + // get the packet length bit width + std::string typeStr = plNode.attribute("type").value(); + std::string::size_type spos = typeStr.find_first_of("0123456789"); + std::string::size_type epos = typeStr.find_last_of("0123456789"); + int nbits = atoi(typeStr.substr(spos, epos+1).c_str()); + + // load the header + delete headerReference; + headerReference = new PacketHeader(); + headerReference->loadHeader(hNode, plIndex, nbits); + dimHeader = headerReference->size(); + + // load the packet not recognized + PacketNotRecognized* p = new PacketNotRecognized(bigendian); + p->createPacketType(hNode, prefix, dimPrefix); + + packetType[numberOfPacketType] = p; + numberOfPacketType++; + + // load packet types + pugi::xml_node pNode = sNode.child("packet"); + while(pNode) { + if(pNode.attribute("name") != 0) + { + Packet* p = new Packet(bigendian); + p->createPacketType(doc, hNode, plIndex, nbits, pNode, prefix, dimPrefix, physicalIndex); + packetType[numberOfPacketType] = p; + p->setPacketID(numberOfPacketType); + numberOfPacketType++; + } + pNode = pNode.next_sibling(); + } +} bool PacketStream::createStreamStructure() throw(PacketException*) { + if(filenameConfig.find(".xml") != std::string::npos) + { + createStreamStructureXml(); + return true; + } + ConfigurationFile config; char* line; char **argv = new char* [1]; - argv[0] = filenameConfig; + argv[0] = (char*) filenameConfig.c_str(); //cout << "@@@@@@@@@@OPEN " << filenameConfig << endl; try { @@ -276,14 +416,14 @@ bool PacketStream::createStreamStructure() throw(PacketException*) catch(PacketExceptionIO* e) { e->add(" - "); - e->add(filenameConfig); + e->add(filenameConfig.c_str()); e->add("Configuration file: "); throw e; } catch(PacketExceptionFileFormat* e) { e->add(" - "); - e->add(filenameConfig); + e->add(filenameConfig.c_str()); e->add("Configuration file: "); throw e; } @@ -318,7 +458,7 @@ Packet* PacketStream::getPacketType(int index) Packet* PacketStream::getPacketType(string name) { for(int i=1; i<numberOfPacketType; i++) { string pname = packetType[i]->getName(); - if(pname == name) + if(pname.compare(name) == 0) return packetType[i]; } throw new PacketException("Packet type not found in the PacketStream"); diff --git a/src/PartOfPacket.cpp b/src/PartOfPacket.cpp index 0869150a8671fbdb449e14ba72a3a06af222eec5..749a48b4ed0f8bba87b04a01058ab5c369925844 100644 --- a/src/PartOfPacket.cpp +++ b/src/PartOfPacket.cpp @@ -61,11 +61,11 @@ string* PartOfPacket::printStructure() Field* f = fields[i]; if(first) { - sprintf(s, "Prog: %d - Name - %s\n", f->getProgressiv(), f->getName() ); + sprintf(s, "Prog: %d - Name - %s\n", f->getProgressiv(), f->getName().c_str() ); first = false; } else - sprintf(s, "%sProg: %d - Name - %s\n", s, f->getProgressiv(), f->getName() ); + sprintf(s, "%sProg: %d - Name - %s\n", s, f->getProgressiv(), f->getName().c_str() ); } string* sr = new string(s); return sr; @@ -86,6 +86,148 @@ bool PartOfPacket::loadFields(InputText& fp) throw(PacketException*) } */ +const std::string fixed32[] = { "uint32", "int32", "float" }; +const std::string fixed64[] = { "uint64", "int64", "double" }; + +void PartOfPacket::loadFields(pugi::xml_node node) +{ + // it calls the function that releases the memory + deleteFields(); + + // count physical node fields + unsigned int count = 0; + for(pugi::xml_node_iterator it=node.begin(); it != node.end(); ++it) + { + if(string(it->name()).compare("field") == 0) + { + string typeStr = it->attribute("type").value(); + bool found = false; + for(unsigned int i=0; i<3; i++) + { + if(typeStr.compare(fixed32[i]) == 0) + { + count += 2; + found = true; + break; + } + if(typeStr.compare(fixed64[i]) == 0) + { + count += 4; + found = true; + break; + } + } + if(!found) + count++; + } + } + + fields = new Field*[count]; + + // field parsing + for(pugi::xml_node_iterator it=node.begin(); it != node.end(); ++it) + { + if(string(it->name()).compare("field") != 0) + continue; + + string typeStr = it->attribute("type").value(); + bool found = false; + string name, dimension, value; +#ifdef DEBUG + std::cout << "adding fields["<< numberOfFields << "] '" << it->attribute("name").value() << "' " << typeStr << std::endl; +#endif + for(unsigned int i=0; i<3; i++) + { + if(typeStr.compare(fixed32[i]) == 0) + { + name = it->attribute("name").value(); + dimension = "16"; + value = "none"; + Field* f = new Field(name, dimension, value, numberOfFields); + fieldsDimension += f->size(); + fields[numberOfFields] = f; + numberOfFields++; + + name = it->attribute("name").value(); + name += "__1"; + dimension = "16"; + value = "none"; + f = new Field(name, dimension, value, numberOfFields); + fieldsDimension += f->size(); + fields[numberOfFields] = f; + numberOfFields++; + + found = true; + break; + } + } + if(found) + continue; + + // write 64bits fields + for(unsigned int i=0; i<3; i++) + { + if(typeStr.compare(fixed64[i]) == 0) + { + name = it->attribute("name").value(); + dimension = "16"; + value = "none"; + Field* f = new Field(name, dimension, value, numberOfFields); + fieldsDimension += f->size(); + fields[numberOfFields] = f; + numberOfFields++; + + name = it->attribute("name").value(); + name += "__1"; + dimension = "16"; + value = "none"; + f = new Field(name, dimension, value, numberOfFields); + fieldsDimension += f->size(); + fields[numberOfFields] = f; + numberOfFields++; + + name = it->attribute("name").value(); + name += "__2"; + dimension = "16"; + value = "none"; + f = new Field(name, dimension, value, numberOfFields); + fieldsDimension += f->size(); + fields[numberOfFields] = f; + numberOfFields++; + + name = it->attribute("name").value(); + name += "__3"; + dimension = "16"; + value = "none"; + f = new Field(name, dimension, value, numberOfFields); + fieldsDimension += f->size(); + fields[numberOfFields] = f; + numberOfFields++; + + found = true; + break; + } + } + if(found) + continue; + + // write <= 16 bits fields + name = it->attribute("name").value(); + string::size_type spos = typeStr.find_first_of("0123456789"); + string::size_type epos = typeStr.find_last_of("0123456789"); + dimension = typeStr.substr(spos, epos+1).c_str(); + pugi::xml_attribute constvalue = it->attribute("constvalue"); + if(!constvalue) + value = "none"; + else + value = constvalue.value(); + Field* f = new Field(name, dimension, value, numberOfFields); + fieldsDimension += f->size(); + fields[numberOfFields] = f; + numberOfFields++; + } +} + bool PartOfPacket::loadFields(InputText& fp) throw(PacketException*) { char* name, *dimension, *value; @@ -250,6 +392,9 @@ bool PartOfPacket::decode() { { ftemp = fields[i]; dimbit = ftemp->size(); +#ifdef DEBUG + std::cout << "number of bits: " << (int)dimbit << std::endl; +#endif /// Temporary word to be modified for the elaboration word wordtemp; // swap bytes if the machine is bigendian and the stream is little endian and vice-versa. diff --git a/src/SDFBlock.cpp b/src/SDFBlock.cpp index f6d2ed9fe4462d68b285549693c187ed52cfdfe1..7c3c71168642291c7c217b03ed231ce380bc0c7f 100644 --- a/src/SDFBlock.cpp +++ b/src/SDFBlock.cpp @@ -14,7 +14,8 @@ * For commercial purpose see appropriate license terms * * * ***************************************************************************/ - + +#include <sstream> #include "SDFBlock.h" #include "ConfigurationFile.h" #include "PacketExceptionFileFormat.h" @@ -30,6 +31,137 @@ SDFBlockType::SDFBlockType() // cout << "SDFBlockType::SDFBlockType " << sizeof(SDFBlockType) << endl; } +void SDFBlockType::loadType(pugi::xml_node node, const pugi::xml_document& doc, + std::map<pugi::xml_node, int>& physicalIndex) +{ + nblockmax = 0; + + const char* popName = node.attribute("name").value(); + + int dimline = strlen(popName); + name = (char*) new char[dimline+1]; + strncpy(name, popName, dimline+1); + + pugi::xml_node fNode = node.child("field"); + if(fNode) + fixedPresent = true; + else + fixedPresent = false; + + variablePresent = false; + pugi::xpath_node_set rbNodeSet = node.select_nodes("rblock"); + if(rbNodeSet.size() == 0) + { + 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) + 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; + + 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) + { + // 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; + } + 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); + } + + rblockFilename[i] = (char*) rbNode.attribute("name").value(); + } + + nblockmax += maxNumberOfBlock[i]; + } + } + else + { + numberOfRBlocks = 0; + rblockFilename = 0; + rBlockVariable = 0; + maxNumberOfBlock = 0; + indexOfNBlock = 0; + subFromNBlock = 0; + numberOfBlockFixed = 0; + headerLevelOfNBlockIndex = 0; + operatorType = 0; + } +} + bool SDFBlockType::loadType(InputText& fp) throw(PacketException*) { @@ -232,6 +364,71 @@ SDFBlock::~SDFBlock() delete[] block; } +void SDFBlock::loadFields(pugi::xml_node rbNode, const pugi::xml_document& doc, + std::map<pugi::xml_node, int>& physicalIndex) +{ + popName = (char*) rbNode.attribute("name").value(); + dword indexlist = 0; + type = 0; + while(blockTypeList[indexlist] != 0) + { + if(strcmp(blockTypeList[indexlist]->name, popName) == 0) + { + type = blockTypeList[indexlist]; + break; + } + else + indexlist++; + } + + this->previous = previous; + if(type == 0) + { +// cout << "create the type " << popName << endl; + type = new SDFBlockType; + blockTypeList[indexlist] = type; + type->loadType(rbNode, doc, physicalIndex); + } + +// cout << "NZ " << type->name << endl; + if(type->variablePresent) + numberOfRealDataBlock = new word[type->numberOfRBlocks]; + else + numberOfRealDataBlock = 0; + + /// It loads the fixed part (if present) + fixed.previous = previous; + if(type->fixedPresent) + fixed.loadFields(rbNode); + + if(type->variablePresent) + { + for(int i=0; i< type->numberOfRBlocks; i++) + if(type->rBlockVariable[i] == false) + numberOfRealDataBlock[i] = type->maxNumberOfBlock[i]; + + block = (SDFBlock*) new SDFBlock[type->nblockmax]; + int indexRBlock = 0; + dword sumBlock = type->maxNumberOfBlock[indexRBlock]; + word id = 0; + for(dword nblock=0; nblock < type->nblockmax; nblock++) + { + if(nblock >= sumBlock) + { + indexRBlock++; + id = 0; + sumBlock += type->maxNumberOfBlock[indexRBlock]; + } + + block[nblock].setPreviousPop(&fixed); + block[nblock].setRBlockType(indexRBlock); + block[nblock].setID(id); + pugi::xml_node childNode = rbNode.child(type->rblockFilename[indexRBlock]); + block[nblock].loadFields(childNode, doc, physicalIndex); + id++; + } + } +} bool SDFBlock::loadFields(InputText& fp) throw (PacketException*) { diff --git a/src/SourceDataField.cpp b/src/SourceDataField.cpp index c3e7d2de4debd425f52bbcd7183db57ec83cb339..aca8a8bef4658f726e691c32e7a293d07e07084a 100644 --- a/src/SourceDataField.cpp +++ b/src/SourceDataField.cpp @@ -51,6 +51,24 @@ SourceDataField::~SourceDataField() } +void SourceDataField::loadFields(pugi::xml_node node, const pugi::xml_document& doc, std::map<pugi::xml_node, int>& physicalIndex) +{ + numberOfRBlocks = 1; + rblockFilename = new char*[numberOfRBlocks]; + numberOfBlockFixed[0] = true; + maxNumberOfBlock[0] = 1; + numberOfRealDataBlock[0] = 1; + indexOfNBlock[0] = 0; + subFromNBlock[0] = 0; + rblockFilename[0]= (char*)"Source Data Field"; + nblockmax = 1; + block = (SDFBlock*) new SDFBlock[nblockmax]; + block[0].setPreviousPop(previous); + block[0].setRBlockType(0); + block[0].setID(0); + block[0].loadFields(node, doc, physicalIndex); +} + bool SourceDataField::loadFields(InputText& fp) throw(PacketException*) { try