RideFile* readBlocks(const QByteArray& blocks, const qint16 version, QStringList& /*errors*/) { RideFile* rideFile = new RideFile(); rideFile->setDeviceType(TACX_FORTIUS_DEVICE_TYPE); rideFile->setFileFormat("Tacx Fortius (caf)"); QByteArray remainingBytes = blocks; while(!remainingBytes.isEmpty()) { const QByteArray blockHeaderBytes = remainingBytes.left(12); header_t blockHeader = readBlockHeader(blockHeaderBytes); switch(blockHeader.fingerprint) { case TACX_RIDE_INFORMATION_BLOCK: readRideInformationBlock(rideFile, remainingBytes.mid(12)); break; case TACX_RIDE_DATA_BLOCK: readRideData(rideFile, remainingBytes.mid(12), blockHeader.recordCount, version); break; } int skipBytes = 12 + blockHeader.recordCount * blockHeader.recordSize; remainingBytes = remainingBytes.mid(skipBytes); } return rideFile; }
// Read one file header block. Returns: // -1 ... this was the last block // 0 ... there is at least one more block left // 1 ... error occured during reading the block // Arguments: // f ... pointer to file for reading // debugMode ... debug messages flag // fileName ... name of the file // buf ... pointer to header buffer, // enlarged (reallocated) for current block // bufOffset ... pointer to buffer size, increased for current block size int readHeaderBlock(FILE *f, int debugMode, const char *fileName, char **buf, int *bufOffset) { char *tmpBuf; int error, blockHeader[blockHeaderSize], swap; // Get size of file header block. swap = readBlockHeader(f, fileName, debugMode, blockHeader, sizeof(char)); if(swap < 0) return 1; // Error. // Allocate space for buffer. tmpBuf = reallocate(debugMode, *buf, (*bufOffset + blockHeader[0] + 1) * sizeof(char)); if(tmpBuf == NULL) return 1; // Error. *buf = tmpBuf; // Read file header block. error = readBlockData(f, fileName, debugMode, *buf + *bufOffset, bufOffset, sizeof(char), blockHeader[0], 0); if(error == 1) return 1; // Error. (*buf)[*bufOffset] = 0; // Read trailer of file header block. error = readBlockTrailer(f, fileName, debugMode, swap, blockHeader[blockHeaderSize - 1]); if(error == 1) return 1; // Error. if(strstr(*buf, "$&%#")) return -1; // End of block. return 0; // There is more. }
// Read one data block. Returns: // -1 ... this was the last block // 0 ... there is at least one more block left // 1 ... error occured during reading the block // Arguments: // f ... pointer to file for reading // debugMode ... debug messages flag // fileName ... name of the file // rawData ... pointer to data array, // enlarged (reallocated) for current block // rawDataOffset ... pointer to data array size, increased for current block size int readDataBlock(FILE *f, int debugMode, int postVersion, const char *fileName, float **rawData, int *rawDataOffset) { int error, blockHeader[blockHeaderSize], swap; float *tmpRawData; double endVal; // Get size of raw data block. swap = readBlockHeader(f, fileName, debugMode, blockHeader, sizeof(float)); if(swap < 0) return 1; // Error. // Allocate space for raw data. tmpRawData = reallocate(debugMode, *rawData, (*rawDataOffset + blockHeader[0]) * sizeof(float)); if(tmpRawData == NULL) return 1; // Error. *rawData = tmpRawData; // Read raw data block. error = readBlockData(f, fileName, debugMode, *rawData + *rawDataOffset, rawDataOffset, sizeof(float), blockHeader[0], swap); if(error == 1) return 1; // Error. // Read trailer of file header block. error = readBlockTrailer(f, fileName, debugMode, swap, blockHeader[blockHeaderSize - 1]); if(error == 1) return 1; // Error. if(postVersion == 2001) { endVal = *(double *)(*rawData + *rawDataOffset - 2); } else { endVal = *(*rawData + *rawDataOffset - 1); } if(endVal > 9e29) { if(debugMode) fprintf(debugFile, "%g\n", endVal); return -1; // End of block. } return 0; // There is more. }
void ArcInfoExportFileNode::update(void) { /* Do nothing if there is no export file name: */ if(url.getNumValues()==0) return; /* Open the ARC/INFO export file: */ IO::AutoFile exportFileSource(Comm::openFile(multiplexer,url.getValue(0).c_str())); IO::ValueSource exportFile(*exportFileSource); /* Check the file's format: */ if(exportFile.readString()!="EXP"||exportFile.readInteger()!=0) return; /* Skip the rest of the header line: */ exportFile.skipLine(); exportFile.skipWs(); /* Create a shape node to contain the polylines read from embedded ARC files: */ ShapeNode* arcShape=new ShapeNode; IndexedLineSetNode* arcLineSet=new IndexedLineSetNode; arcShape->geometry.setValue(arcLineSet); ColorNode* arcLineSetColors=new ColorNode; arcLineSet->color.setValue(arcLineSetColors); CoordinateNode* arcLineSetCoords=new CoordinateNode; arcLineSet->coord.setValue(arcLineSetCoords); arcLineSet->colorPerVertex.setValue(false); /* Read embedded files until end-of-file: */ while(!exportFile.eof()) { /* Read the next embedded file's header: */ std::string fileType=exportFile.readString(); if(fileType=="EOS") { /* Marks the end of the file; ignore everything after here: */ break; } else if(fileType=="ARC") { /* Skip the rest of the line: */ exportFile.skipLine(); exportFile.skipWs(); /* Read polylines from the ARC file: */ while(true) { /* Read the next block header: */ int blockHeader[7]; if(!readBlockHeader(exportFile,blockHeader)||blockHeader[0]==-1) break; /* Read all vertices in this polyline: */ for(int i=0;i<blockHeader[6];++i) { /* Read the next vertex's 2D position: */ double px=exportFile.readNumber(); double py=exportFile.readNumber(); /* Add the vertex to the current polyline: */ arcLineSet->coordIndex.appendValue(arcLineSetCoords->point.getNumValues()); arcLineSetCoords->point.appendValue(Point(px,py,0)); } /* Finalize the current polyline: */ arcLineSet->coordIndex.appendValue(-1); arcLineSetColors->color.appendValue(Color(1.0f,1.0f,1.0f)); } } else if(fileType=="SIN") { /* Skip a SIN file: */ while(!exportFile.eof()&&exportFile.readString()!="EOX") ; } else if(fileType=="LOG") { /* Skip a LOG file: */ while(!exportFile.eof()&&exportFile.readString()!="EOL") ; } else if(fileType=="PRJ") { /* Skip a PRJ file: */ while(!exportFile.eof()&&exportFile.readString()!="EOP") ; } else if(fileType=="TX6"||fileType=="TX7"||fileType=="RXP"||fileType=="RPL") { /* Skip a text file: */ while(!exportFile.eof()&&exportFile.readString()!="JABBERWOCKY") // What the hell? ; } else if(fileType=="MTD") { /* Skip a MTD file: */ while(!exportFile.eof()&&exportFile.readString()!="EOD") ; } else if(fileType=="IFO") { /* Skip a IFO file: */ while(!exportFile.eof()&&exportFile.readString()!="EOI") ; } else { /* Temporarily mark newline characters as punctuation: */ exportFile.setPunctuation('\n',true); /* Skip an unrecognized file: */ while(!exportFile.eof()) { /* Try to read a block header: */ int values[7]; if(readBlockHeader(exportFile,values)&&values[0]==-1) break; /* Skip the rest of the line: */ exportFile.skipLine(); exportFile.skipWs(); } /* Mark newline characters as whitespace again: */ exportFile.setWhitespace('\n',true); } } /* Finalize the generated nodes: */ arcLineSetColors->update(); arcLineSetCoords->update(); arcLineSet->update(); arcShape->update(); /* Store all generated nodes as children: */ children.appendValue(arcShape); GroupNode::update(); }