giuliomoro@153: /* giuliomoro@153: * WriteFile.cpp giuliomoro@153: * giuliomoro@153: * Created on: 5 Oct 2015 giuliomoro@153: * Author: giulio giuliomoro@153: */ giuliomoro@153: giuliomoro@153: #include "WriteFile.h" giuliomoro@153: //initialise static members giuliomoro@153: bool WriteFile::staticConstructed=false; giuliomoro@153: AuxiliaryTask WriteFile::writeAllFilesTask=NULL; giuliomoro@153: std::vector WriteFile::objAddrs(0); giuliomoro@153: bool WriteFile::threadRunning; giuliomoro@153: bool WriteFile::threadIsExiting; giuliomoro@153: int WriteFile::sleepTimeMs; giuliomoro@153: giuliomoro@153: void WriteFile::staticConstructor(){ giuliomoro@153: if(staticConstructed==true) giuliomoro@153: return; giuliomoro@153: staticConstructed=true; giuliomoro@153: threadIsExiting=false; giuliomoro@153: threadRunning=false; giuliomoro@153: writeAllFilesTask = BeagleRT_createAuxiliaryTask(WriteFile::run, 60, "writeAllFilesTask"); giuliomoro@153: } giuliomoro@153: giuliomoro@153: WriteFile::WriteFile(){ giuliomoro@153: buffer = NULL; giuliomoro@153: format = NULL; giuliomoro@153: header = NULL; giuliomoro@153: footer = NULL; giuliomoro@153: stringBuffer = NULL; giuliomoro@153: }; giuliomoro@153: giuliomoro@153: void WriteFile::init(const char* filename){ //if you do not call this before using the object, results are undefined giuliomoro@153: file = fopen(filename, "w"); giuliomoro@153: variableOpen = false; giuliomoro@153: lineLength = 0; giuliomoro@153: echo = false; giuliomoro@153: bufferLength = 0; giuliomoro@153: readPointer = 0; giuliomoro@153: writePointer = 0; giuliomoro@153: sleepTimeMs = 1; giuliomoro@153: stringBufferLength = 1000; giuliomoro@153: stringBuffer = (char*)malloc(sizeof(char) * (stringBufferLength)); giuliomoro@153: setHeader("variable=[\n"); giuliomoro@153: setFooter("];\n"); giuliomoro@153: staticConstructor(); //TODO: this line should be in the constructor, but cannot because of a bug in BeagleRT giuliomoro@153: objAddrs.push_back(this); giuliomoro@153: } giuliomoro@153: giuliomoro@153: void WriteFile::setEcho(bool newEcho){ giuliomoro@153: echo=newEcho; giuliomoro@153: } giuliomoro@153: giuliomoro@153: void WriteFile::print(const char* string){ giuliomoro@153: if(echo == true){ giuliomoro@153: printf("%s", string); giuliomoro@153: } giuliomoro@153: if(file != NULL){ giuliomoro@153: fprintf(file, "%s", string); giuliomoro@153: } giuliomoro@153: } giuliomoro@153: giuliomoro@153: void WriteFile::writeLine(){ giuliomoro@153: int stringBufferPointer = 0; giuliomoro@153: for(unsigned int n = 0; n < formatTokens.size(); n++){ giuliomoro@153: int numOfCharsWritten = snprintf( &stringBuffer[stringBufferPointer], stringBufferLength - stringBufferPointer, giuliomoro@153: formatTokens[n], buffer[readPointer]); giuliomoro@153: stringBufferPointer += numOfCharsWritten; giuliomoro@153: readPointer++; giuliomoro@153: if (readPointer >= bufferLength){ giuliomoro@153: readPointer -= bufferLength; giuliomoro@153: } giuliomoro@153: } giuliomoro@153: print(stringBuffer); giuliomoro@153: } giuliomoro@153: giuliomoro@153: void WriteFile::setLineLength(int newLineLength){ giuliomoro@153: lineLength=newLineLength; giuliomoro@153: free(buffer); giuliomoro@153: bufferLength = lineLength * 10000; // circular buffer of length 10000 lineLenghts giuliomoro@153: buffer = (float*)malloc(sizeof(float) * bufferLength); giuliomoro@153: } giuliomoro@153: giuliomoro@153: void WriteFile::log(float value){ giuliomoro@153: if(format == NULL || buffer == NULL) giuliomoro@153: return; giuliomoro@153: buffer[writePointer] = value; giuliomoro@153: writePointer++; giuliomoro@153: if(writePointer == bufferLength){ giuliomoro@153: writePointer = 0; giuliomoro@153: } giuliomoro@153: if(writePointer == readPointer){ giuliomoro@153: fprintf(stderr, "WriteFile: pointers crossed, you should probably write less data to disk\n"); giuliomoro@153: } giuliomoro@153: if(threadRunning == false){ giuliomoro@153: startThread(); giuliomoro@153: } giuliomoro@153: } giuliomoro@153: giuliomoro@153: void WriteFile::log(float* array, int length){ giuliomoro@153: for(int n = 0; n < length; n++){ giuliomoro@153: log(array[n]); giuliomoro@153: } giuliomoro@153: } giuliomoro@153: giuliomoro@153: WriteFile::~WriteFile() { giuliomoro@153: free(format); giuliomoro@153: free(buffer); giuliomoro@153: free(header); giuliomoro@153: free(footer); giuliomoro@153: free(stringBuffer); giuliomoro@153: } giuliomoro@153: giuliomoro@153: void WriteFile::setFormat(const char* newFormat){ giuliomoro@153: allocateAndCopyString(newFormat, &format); giuliomoro@153: for(unsigned int n = 0; n < formatTokens.size(); n++){ giuliomoro@153: free(formatTokens[n]); giuliomoro@153: } giuliomoro@153: formatTokens.clear(); giuliomoro@153: int tokenStart = 0; giuliomoro@153: bool firstToken = true; giuliomoro@153: for(unsigned int n = 0; n < strlen(format)+1; n++){ giuliomoro@153: if(format[n] == '%' && format[n + 1] == '%'){ giuliomoro@153: n++; giuliomoro@153: } else if (format[n] == '%' || format[n] == 0){ giuliomoro@153: if(firstToken == true){ giuliomoro@153: firstToken = false; giuliomoro@153: continue; giuliomoro@153: } giuliomoro@153: char* string; giuliomoro@153: unsigned int tokenLength = n - tokenStart; giuliomoro@153: if(tokenLength == 0) giuliomoro@153: continue; giuliomoro@153: string = (char*)malloc((1+tokenLength)*sizeof(char)); giuliomoro@153: for(unsigned int i = 0; i < tokenLength; i++){ giuliomoro@153: string[i] = format[tokenStart + i]; giuliomoro@153: } giuliomoro@153: string[tokenLength] = 0; giuliomoro@153: formatTokens.push_back(string); giuliomoro@153: tokenStart = n; giuliomoro@153: } giuliomoro@153: } giuliomoro@153: setLineLength(formatTokens.size()); giuliomoro@153: } giuliomoro@153: giuliomoro@153: int WriteFile::getNumInstances(){ giuliomoro@153: return objAddrs.size(); giuliomoro@153: } giuliomoro@153: giuliomoro@153: void WriteFile::startThread(){ giuliomoro@153: BeagleRT_scheduleAuxiliaryTask(writeAllFilesTask); giuliomoro@153: } giuliomoro@153: giuliomoro@153: void WriteFile::stopThread(){ giuliomoro@153: threadIsExiting=true; giuliomoro@153: } giuliomoro@153: giuliomoro@153: bool WriteFile::threadShouldExit(){ giuliomoro@153: return(gShouldStop || threadIsExiting); giuliomoro@153: } giuliomoro@153: giuliomoro@153: bool WriteFile::isThreadRunning(){ giuliomoro@153: return threadRunning; giuliomoro@153: } giuliomoro@153: giuliomoro@153: float WriteFile::getBufferStatus(){ giuliomoro@153: return 1-getOffset()/(float)bufferLength; giuliomoro@153: } giuliomoro@153: giuliomoro@153: int WriteFile::getOffset(){ giuliomoro@153: int offset = writePointer - readPointer; giuliomoro@153: if( offset < 0) giuliomoro@153: offset += bufferLength; giuliomoro@153: return offset; giuliomoro@153: } giuliomoro@153: giuliomoro@153: void WriteFile::writeOutput(){ giuliomoro@153: while( getOffset() >= lineLength ){ //if there is less than one line worth of data to write, skip over. giuliomoro@153: // So we make sure we always write full lines giuliomoro@153: writeLine(); giuliomoro@153: } giuliomoro@153: } giuliomoro@153: giuliomoro@153: void WriteFile::writeAllOutputs(){ giuliomoro@153: for(unsigned int n = 0; n < objAddrs.size(); n++){ giuliomoro@153: objAddrs[n] -> writeOutput(); giuliomoro@153: } giuliomoro@153: } giuliomoro@153: giuliomoro@153: void WriteFile::writeAllHeaders(){ giuliomoro@153: for(unsigned int n = 0; n < objAddrs.size(); n++){ giuliomoro@153: objAddrs[n] -> writeHeader(); giuliomoro@153: } giuliomoro@153: } giuliomoro@153: giuliomoro@153: void WriteFile::writeAllFooters(){ giuliomoro@153: for(unsigned int n = 0; n < objAddrs.size(); n++){ giuliomoro@153: objAddrs[n] -> writeFooter(); giuliomoro@153: } giuliomoro@153: } giuliomoro@153: giuliomoro@153: void WriteFile::writeHeader(){ giuliomoro@153: print(header); giuliomoro@153: } giuliomoro@153: giuliomoro@153: void WriteFile::writeFooter(){ giuliomoro@153: print(footer); giuliomoro@153: fflush(file); giuliomoro@153: fclose(file); giuliomoro@153: } giuliomoro@153: giuliomoro@153: void WriteFile::setHeader(const char* newHeader){ giuliomoro@153: allocateAndCopyString(newHeader, &header); giuliomoro@153: sanitizeString(header); giuliomoro@153: } giuliomoro@153: giuliomoro@153: void WriteFile::setFooter(const char* newFooter){ giuliomoro@153: allocateAndCopyString(newFooter, &footer); giuliomoro@153: } giuliomoro@153: giuliomoro@153: void WriteFile::sanitizeString(char* string){ giuliomoro@153: for(int unsigned n = 0; n < strlen(string); n++){ //purge %'s from the string giuliomoro@153: if(string[n] == '%'){ giuliomoro@153: string[n] = ' '; giuliomoro@153: } giuliomoro@153: } giuliomoro@153: } giuliomoro@153: giuliomoro@153: void WriteFile::run(){ giuliomoro@153: threadRunning = true; giuliomoro@153: writeAllHeaders(); giuliomoro@153: while(threadShouldExit()==false){ giuliomoro@153: writeAllOutputs(); giuliomoro@153: usleep(sleepTimeMs*1000); giuliomoro@153: } giuliomoro@153: writeAllFooters(); // when ctrl-c is pressed, the last line is closed and the file is closed giuliomoro@153: threadRunning = false; giuliomoro@153: } giuliomoro@153: giuliomoro@153: void WriteFile::allocateAndCopyString(const char* source, char** destination){ giuliomoro@153: free(*destination); giuliomoro@153: *destination = (char*)malloc(sizeof(char) * (strlen(source) + 1)); giuliomoro@153: strcpy(*destination, source); giuliomoro@153: }