giuliomoro@153
|
1 /*
|
giuliomoro@153
|
2 * WriteFile.cpp
|
giuliomoro@153
|
3 *
|
giuliomoro@153
|
4 * Created on: 5 Oct 2015
|
giuliomoro@153
|
5 * Author: giulio
|
giuliomoro@153
|
6 */
|
giuliomoro@153
|
7
|
giuliomoro@153
|
8 #include "WriteFile.h"
|
giuliomoro@153
|
9 //initialise static members
|
giuliomoro@153
|
10 bool WriteFile::staticConstructed=false;
|
giuliomoro@153
|
11 AuxiliaryTask WriteFile::writeAllFilesTask=NULL;
|
giuliomoro@153
|
12 std::vector<WriteFile *> WriteFile::objAddrs(0);
|
giuliomoro@153
|
13 bool WriteFile::threadRunning;
|
giuliomoro@153
|
14 bool WriteFile::threadIsExiting;
|
giuliomoro@153
|
15 int WriteFile::sleepTimeMs;
|
giuliomoro@153
|
16
|
giuliomoro@153
|
17 void WriteFile::staticConstructor(){
|
giuliomoro@153
|
18 if(staticConstructed==true)
|
giuliomoro@153
|
19 return;
|
giuliomoro@153
|
20 staticConstructed=true;
|
giuliomoro@153
|
21 threadIsExiting=false;
|
giuliomoro@153
|
22 threadRunning=false;
|
giuliomoro@153
|
23 writeAllFilesTask = BeagleRT_createAuxiliaryTask(WriteFile::run, 60, "writeAllFilesTask");
|
giuliomoro@153
|
24 }
|
giuliomoro@153
|
25
|
giuliomoro@153
|
26 WriteFile::WriteFile(){
|
giuliomoro@153
|
27 buffer = NULL;
|
giuliomoro@153
|
28 format = NULL;
|
giuliomoro@153
|
29 header = NULL;
|
giuliomoro@153
|
30 footer = NULL;
|
giuliomoro@153
|
31 stringBuffer = NULL;
|
giuliomoro@153
|
32 };
|
giuliomoro@153
|
33
|
giuliomoro@153
|
34 void WriteFile::init(const char* filename){ //if you do not call this before using the object, results are undefined
|
giuliomoro@153
|
35 file = fopen(filename, "w");
|
giuliomoro@153
|
36 variableOpen = false;
|
giuliomoro@153
|
37 lineLength = 0;
|
giuliomoro@153
|
38 echo = false;
|
giuliomoro@153
|
39 bufferLength = 0;
|
giuliomoro@153
|
40 readPointer = 0;
|
giuliomoro@153
|
41 writePointer = 0;
|
giuliomoro@153
|
42 sleepTimeMs = 1;
|
giuliomoro@153
|
43 stringBufferLength = 1000;
|
giuliomoro@153
|
44 stringBuffer = (char*)malloc(sizeof(char) * (stringBufferLength));
|
giuliomoro@153
|
45 setHeader("variable=[\n");
|
giuliomoro@153
|
46 setFooter("];\n");
|
giuliomoro@153
|
47 staticConstructor(); //TODO: this line should be in the constructor, but cannot because of a bug in BeagleRT
|
giuliomoro@153
|
48 objAddrs.push_back(this);
|
giuliomoro@153
|
49 }
|
giuliomoro@153
|
50
|
giuliomoro@153
|
51 void WriteFile::setEcho(bool newEcho){
|
giuliomoro@153
|
52 echo=newEcho;
|
giuliomoro@153
|
53 }
|
giuliomoro@153
|
54
|
giuliomoro@153
|
55 void WriteFile::print(const char* string){
|
giuliomoro@153
|
56 if(echo == true){
|
giuliomoro@153
|
57 printf("%s", string);
|
giuliomoro@153
|
58 }
|
giuliomoro@153
|
59 if(file != NULL){
|
giuliomoro@153
|
60 fprintf(file, "%s", string);
|
giuliomoro@153
|
61 }
|
giuliomoro@153
|
62 }
|
giuliomoro@153
|
63
|
giuliomoro@153
|
64 void WriteFile::writeLine(){
|
giuliomoro@153
|
65 int stringBufferPointer = 0;
|
giuliomoro@153
|
66 for(unsigned int n = 0; n < formatTokens.size(); n++){
|
giuliomoro@153
|
67 int numOfCharsWritten = snprintf( &stringBuffer[stringBufferPointer], stringBufferLength - stringBufferPointer,
|
giuliomoro@153
|
68 formatTokens[n], buffer[readPointer]);
|
giuliomoro@153
|
69 stringBufferPointer += numOfCharsWritten;
|
giuliomoro@153
|
70 readPointer++;
|
giuliomoro@153
|
71 if (readPointer >= bufferLength){
|
giuliomoro@153
|
72 readPointer -= bufferLength;
|
giuliomoro@153
|
73 }
|
giuliomoro@153
|
74 }
|
giuliomoro@153
|
75 print(stringBuffer);
|
giuliomoro@153
|
76 }
|
giuliomoro@153
|
77
|
giuliomoro@153
|
78 void WriteFile::setLineLength(int newLineLength){
|
giuliomoro@153
|
79 lineLength=newLineLength;
|
giuliomoro@153
|
80 free(buffer);
|
giuliomoro@153
|
81 bufferLength = lineLength * 10000; // circular buffer of length 10000 lineLenghts
|
giuliomoro@153
|
82 buffer = (float*)malloc(sizeof(float) * bufferLength);
|
giuliomoro@153
|
83 }
|
giuliomoro@153
|
84
|
giuliomoro@153
|
85 void WriteFile::log(float value){
|
giuliomoro@153
|
86 if(format == NULL || buffer == NULL)
|
giuliomoro@153
|
87 return;
|
giuliomoro@153
|
88 buffer[writePointer] = value;
|
giuliomoro@153
|
89 writePointer++;
|
giuliomoro@153
|
90 if(writePointer == bufferLength){
|
giuliomoro@153
|
91 writePointer = 0;
|
giuliomoro@153
|
92 }
|
giuliomoro@153
|
93 if(writePointer == readPointer){
|
giuliomoro@153
|
94 fprintf(stderr, "WriteFile: pointers crossed, you should probably write less data to disk\n");
|
giuliomoro@153
|
95 }
|
giuliomoro@153
|
96 if(threadRunning == false){
|
giuliomoro@153
|
97 startThread();
|
giuliomoro@153
|
98 }
|
giuliomoro@153
|
99 }
|
giuliomoro@153
|
100
|
giuliomoro@153
|
101 void WriteFile::log(float* array, int length){
|
giuliomoro@153
|
102 for(int n = 0; n < length; n++){
|
giuliomoro@153
|
103 log(array[n]);
|
giuliomoro@153
|
104 }
|
giuliomoro@153
|
105 }
|
giuliomoro@153
|
106
|
giuliomoro@153
|
107 WriteFile::~WriteFile() {
|
giuliomoro@153
|
108 free(format);
|
giuliomoro@153
|
109 free(buffer);
|
giuliomoro@153
|
110 free(header);
|
giuliomoro@153
|
111 free(footer);
|
giuliomoro@153
|
112 free(stringBuffer);
|
giuliomoro@153
|
113 }
|
giuliomoro@153
|
114
|
giuliomoro@153
|
115 void WriteFile::setFormat(const char* newFormat){
|
giuliomoro@153
|
116 allocateAndCopyString(newFormat, &format);
|
giuliomoro@153
|
117 for(unsigned int n = 0; n < formatTokens.size(); n++){
|
giuliomoro@153
|
118 free(formatTokens[n]);
|
giuliomoro@153
|
119 }
|
giuliomoro@153
|
120 formatTokens.clear();
|
giuliomoro@153
|
121 int tokenStart = 0;
|
giuliomoro@153
|
122 bool firstToken = true;
|
giuliomoro@153
|
123 for(unsigned int n = 0; n < strlen(format)+1; n++){
|
giuliomoro@153
|
124 if(format[n] == '%' && format[n + 1] == '%'){
|
giuliomoro@153
|
125 n++;
|
giuliomoro@153
|
126 } else if (format[n] == '%' || format[n] == 0){
|
giuliomoro@153
|
127 if(firstToken == true){
|
giuliomoro@153
|
128 firstToken = false;
|
giuliomoro@153
|
129 continue;
|
giuliomoro@153
|
130 }
|
giuliomoro@153
|
131 char* string;
|
giuliomoro@153
|
132 unsigned int tokenLength = n - tokenStart;
|
giuliomoro@153
|
133 if(tokenLength == 0)
|
giuliomoro@153
|
134 continue;
|
giuliomoro@153
|
135 string = (char*)malloc((1+tokenLength)*sizeof(char));
|
giuliomoro@153
|
136 for(unsigned int i = 0; i < tokenLength; i++){
|
giuliomoro@153
|
137 string[i] = format[tokenStart + i];
|
giuliomoro@153
|
138 }
|
giuliomoro@153
|
139 string[tokenLength] = 0;
|
giuliomoro@153
|
140 formatTokens.push_back(string);
|
giuliomoro@153
|
141 tokenStart = n;
|
giuliomoro@153
|
142 }
|
giuliomoro@153
|
143 }
|
giuliomoro@153
|
144 setLineLength(formatTokens.size());
|
giuliomoro@153
|
145 }
|
giuliomoro@153
|
146
|
giuliomoro@153
|
147 int WriteFile::getNumInstances(){
|
giuliomoro@153
|
148 return objAddrs.size();
|
giuliomoro@153
|
149 }
|
giuliomoro@153
|
150
|
giuliomoro@153
|
151 void WriteFile::startThread(){
|
giuliomoro@153
|
152 BeagleRT_scheduleAuxiliaryTask(writeAllFilesTask);
|
giuliomoro@153
|
153 }
|
giuliomoro@153
|
154
|
giuliomoro@153
|
155 void WriteFile::stopThread(){
|
giuliomoro@153
|
156 threadIsExiting=true;
|
giuliomoro@153
|
157 }
|
giuliomoro@153
|
158
|
giuliomoro@153
|
159 bool WriteFile::threadShouldExit(){
|
giuliomoro@153
|
160 return(gShouldStop || threadIsExiting);
|
giuliomoro@153
|
161 }
|
giuliomoro@153
|
162
|
giuliomoro@153
|
163 bool WriteFile::isThreadRunning(){
|
giuliomoro@153
|
164 return threadRunning;
|
giuliomoro@153
|
165 }
|
giuliomoro@153
|
166
|
giuliomoro@153
|
167 float WriteFile::getBufferStatus(){
|
giuliomoro@153
|
168 return 1-getOffset()/(float)bufferLength;
|
giuliomoro@153
|
169 }
|
giuliomoro@153
|
170
|
giuliomoro@153
|
171 int WriteFile::getOffset(){
|
giuliomoro@153
|
172 int offset = writePointer - readPointer;
|
giuliomoro@153
|
173 if( offset < 0)
|
giuliomoro@153
|
174 offset += bufferLength;
|
giuliomoro@153
|
175 return offset;
|
giuliomoro@153
|
176 }
|
giuliomoro@153
|
177
|
giuliomoro@153
|
178 void WriteFile::writeOutput(){
|
giuliomoro@153
|
179 while( getOffset() >= lineLength ){ //if there is less than one line worth of data to write, skip over.
|
giuliomoro@153
|
180 // So we make sure we always write full lines
|
giuliomoro@153
|
181 writeLine();
|
giuliomoro@153
|
182 }
|
giuliomoro@153
|
183 }
|
giuliomoro@153
|
184
|
giuliomoro@153
|
185 void WriteFile::writeAllOutputs(){
|
giuliomoro@153
|
186 for(unsigned int n = 0; n < objAddrs.size(); n++){
|
giuliomoro@153
|
187 objAddrs[n] -> writeOutput();
|
giuliomoro@153
|
188 }
|
giuliomoro@153
|
189 }
|
giuliomoro@153
|
190
|
giuliomoro@153
|
191 void WriteFile::writeAllHeaders(){
|
giuliomoro@153
|
192 for(unsigned int n = 0; n < objAddrs.size(); n++){
|
giuliomoro@153
|
193 objAddrs[n] -> writeHeader();
|
giuliomoro@153
|
194 }
|
giuliomoro@153
|
195 }
|
giuliomoro@153
|
196
|
giuliomoro@153
|
197 void WriteFile::writeAllFooters(){
|
giuliomoro@153
|
198 for(unsigned int n = 0; n < objAddrs.size(); n++){
|
giuliomoro@153
|
199 objAddrs[n] -> writeFooter();
|
giuliomoro@153
|
200 }
|
giuliomoro@153
|
201 }
|
giuliomoro@153
|
202
|
giuliomoro@153
|
203 void WriteFile::writeHeader(){
|
giuliomoro@153
|
204 print(header);
|
giuliomoro@153
|
205 }
|
giuliomoro@153
|
206
|
giuliomoro@153
|
207 void WriteFile::writeFooter(){
|
giuliomoro@153
|
208 print(footer);
|
giuliomoro@153
|
209 fflush(file);
|
giuliomoro@153
|
210 fclose(file);
|
giuliomoro@153
|
211 }
|
giuliomoro@153
|
212
|
giuliomoro@153
|
213 void WriteFile::setHeader(const char* newHeader){
|
giuliomoro@153
|
214 allocateAndCopyString(newHeader, &header);
|
giuliomoro@153
|
215 sanitizeString(header);
|
giuliomoro@153
|
216 }
|
giuliomoro@153
|
217
|
giuliomoro@153
|
218 void WriteFile::setFooter(const char* newFooter){
|
giuliomoro@153
|
219 allocateAndCopyString(newFooter, &footer);
|
giuliomoro@153
|
220 }
|
giuliomoro@153
|
221
|
giuliomoro@153
|
222 void WriteFile::sanitizeString(char* string){
|
giuliomoro@153
|
223 for(int unsigned n = 0; n < strlen(string); n++){ //purge %'s from the string
|
giuliomoro@153
|
224 if(string[n] == '%'){
|
giuliomoro@153
|
225 string[n] = ' ';
|
giuliomoro@153
|
226 }
|
giuliomoro@153
|
227 }
|
giuliomoro@153
|
228 }
|
giuliomoro@153
|
229
|
giuliomoro@153
|
230 void WriteFile::run(){
|
giuliomoro@153
|
231 threadRunning = true;
|
giuliomoro@153
|
232 writeAllHeaders();
|
giuliomoro@153
|
233 while(threadShouldExit()==false){
|
giuliomoro@153
|
234 writeAllOutputs();
|
giuliomoro@153
|
235 usleep(sleepTimeMs*1000);
|
giuliomoro@153
|
236 }
|
giuliomoro@153
|
237 writeAllFooters(); // when ctrl-c is pressed, the last line is closed and the file is closed
|
giuliomoro@153
|
238 threadRunning = false;
|
giuliomoro@153
|
239 }
|
giuliomoro@153
|
240
|
giuliomoro@153
|
241 void WriteFile::allocateAndCopyString(const char* source, char** destination){
|
giuliomoro@153
|
242 free(*destination);
|
giuliomoro@153
|
243 *destination = (char*)malloc(sizeof(char) * (strlen(source) + 1));
|
giuliomoro@153
|
244 strcpy(*destination, source);
|
giuliomoro@153
|
245 }
|