Introduced FileSystem and Out classes
[openstranded.git] / src / output.cc
blobd4589bc38acd9bdba19c6cc84de944a5ae7196c1
1 /*
2 * See output.hh for more information about this file
4 * Copyright (C) 2009 David Kolossa
6 * This file is part of OpenStranded.
8 * OpenStranded is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
13 * OpenStranded is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with OpenStranded. If not, see <http://www.gnu.org/licenses/>.
22 #include <iostream>
23 #include <sstream>
24 #include <string>
25 #include <cstdarg>
26 #include <cstdio>
27 #include <cstring>
28 #include <cstdlib>
29 #include <cassert>
30 #ifndef WIN32
31 // Directory handling
32 #include <dirent.h>
33 #include <sys/stat.h>
34 #include <sys/types.h>
35 #endif
36 #include <ctime>
38 #include "filesystem.hh"
39 #include "output.hh"
41 // This constant is used for allocating memory in Printer::printf
42 #define FORMAT_BUFSIZE 100
45 // Printer class
48 Out::Printer::Printer(void printer(std::string))
50 this->printer = printer;
53 Out::Printer&
54 Out::Printer::operator<<(std::string msg)
56 this->printer(msg);
57 return *this;
60 Out::Printer&
61 Out::Printer::operator<<(const char *msg)
63 this->printer(msg);
64 return *this;
67 Out::Printer&
68 Out::Printer::operator<<(char msg)
70 this->printer(std::string(1, msg));
71 return *this;
74 Out::Printer&
75 Out::Printer::operator<<(int msg)
77 std::ostringstream tmp;
78 tmp << msg;
79 this->printer(tmp.str());
80 return *this;
83 Out::Printer&
84 Out::Printer::operator<<(short msg)
86 std::ostringstream tmp;
87 tmp << msg;
88 this->printer(tmp.str());
89 return *this;
92 Out::Printer&
93 Out::Printer::operator<<(long msg)
95 std::ostringstream tmp;
96 tmp << msg;
97 this->printer(tmp.str());
98 return *this;
101 Out::Printer&
102 Out::Printer::operator<<(long long msg)
104 std::ostringstream tmp;
105 tmp << msg;
106 this->printer(tmp.str());
107 return *this;
110 Out::Printer&
111 Out::Printer::operator<<(unsigned int msg)
113 std::ostringstream tmp;
114 tmp << msg;
115 this->printer(tmp.str());
116 return *this;
119 Out::Printer&
120 Out::Printer::operator<<(unsigned short msg)
122 std::ostringstream tmp;
123 tmp << msg;
124 this->printer(tmp.str());
125 return *this;
128 Out::Printer&
129 Out::Printer::operator<<(unsigned long msg)
131 std::ostringstream tmp;
132 tmp << msg;
133 this->printer(tmp.str());
134 return *this;
137 Out::Printer&
138 Out::Printer::operator<<(unsigned long long msg)
140 std::ostringstream tmp;
141 tmp << msg;
142 this->printer(tmp.str());
143 return *this;
146 Out::Printer&
147 Out::Printer::operator<<(float msg)
149 std::ostringstream tmp;
150 tmp << msg;
151 this->printer(tmp.str());
152 return *this;
155 Out::Printer&
156 Out::Printer::operator<<(double msg)
158 std::ostringstream tmp;
159 tmp << msg;
160 this->printer(tmp.str());
161 return *this;
165 Out::Printer::vprintf(const char *format, va_list args)
167 int result;
168 int length = std::strlen(format) + FORMAT_BUFSIZE;
169 char *buffer = new char[length];
171 result = vsprintf(buffer, format, args);
173 if (result)
175 std::ostringstream tmp;
176 tmp << buffer;
177 this->printer(tmp.str());
179 delete[] buffer;
180 return result;
184 Out::Printer::printf(const char *format, ...)
186 int result;
187 va_list args;
188 va_start(args, format);
189 result = this->vprintf(format, args);
190 va_end(args);
191 return result;
197 // Out class
200 Out::Printer Out::fatal = Printer(Out::fatalPrinter);
201 Out::Printer Out::error = Printer(Out::errorPrinter);
202 Out::Printer Out::warning = Printer(Out::warningPrinter);
203 Out::Printer Out::msg = Printer(Out::msgPrinter);
204 Out::Printer Out::debug = Printer(Out::debugPrinter);
206 int Out::isWriting = Out::NONE;
207 int Out::consoleFlags = Out::NONE;
208 int Out::loggingFlags = Out::NONE;
210 FILE *Out::logFile = 0;
213 Out::Out()
217 void
218 Out::setLogFile(std::string fileName)
220 if (Out::logFile != 0)
222 fclose(Out::logFile);
223 Out::logFile = 0;
225 std::string path = "";
226 #ifndef WIN32
227 path += std::getenv("HOME");
228 path += "/.openstranded/";
229 if(opendir(path.c_str()) == NULL)
231 FileSystem::initUserDirectory();
234 #else
235 // TODO: Add Windows directory code.
236 path = "./";
237 #endif
241 path += fileName;
242 Out::logFile = std::fopen(path.c_str(), "a");
243 if(Out::logFile == 0)
245 std::cerr << "FATAL: Log file could not be opened" << std::endl;
246 return;
250 * Timestamp code taken from PeakEngine and modified
251 * <http://peakengine.sourceforge.net/>
253 std::time_t rawtime;
254 std::time(&rawtime);
255 struct std::tm *timeinfo = std::localtime(&rawtime);
256 char timestr[20];
257 std::strftime(timestr, 20, "%x %X", timeinfo);
258 std::fprintf(Out::logFile, "================\nOpened logfile on %s\n================", timestr);
259 std::fflush(Out::logFile);
263 Out::getConsoleFlags()
265 return consoleFlags;
268 void
269 Out::setConsoleFlags(int newflags)
271 consoleFlags = newflags;
275 Out::getLoggingFlags()
277 return loggingFlags;
280 void
281 Out::setLoggingFlags(int newflags)
283 loggingFlags = newflags;
286 void
287 Out::fatalPrinter(std::string msg)
289 if (!(consoleFlags & FATAL) && !(loggingFlags & FATAL))
290 return;
292 // If another command didn't finish its line, fix it for it
293 if((isWriting | FATAL) != FATAL)
295 std::cerr << std::endl;
296 isWriting = 0;
297 debug << "Printed an unfinished line" << endl;
300 // Only write prefix one time per line
301 if((isWriting & FATAL) == 0)
303 msg = "FATAL: " + msg;
306 // If msg is a finished line reset flags, else set flags
307 if(msg.find('\n') == std::string::npos)
309 isWriting = FATAL;
311 else
313 isWriting = 0;
316 if(consoleFlags & FATAL)
318 std::cerr << msg;
321 if(loggingFlags & FATAL)
323 assert(Out::logFile != 0);
324 const char *logMsg = msg.c_str();
325 fwrite(logMsg, std::strlen(logMsg), sizeof(char), Out::logFile);
326 fflush(Out::logFile);
330 void
331 Out::errorPrinter(std::string msg)
333 if (!(consoleFlags & ERROR) && !(loggingFlags & ERROR))
334 return;
336 // If another command didn't finish its line, fix it for it
337 if((isWriting | ERROR) != ERROR)
339 std::cerr << std::endl;
340 debug << "Printed an unfinished line" << endl;
341 isWriting = 0;
344 // Only write prefix one time per line
345 if((isWriting & ERROR) == 0)
347 msg = "ERROR: " + msg;
350 // If msg is a finished line reset consoleFlags, else set flags
351 if(msg.find('\n') == std::string::npos)
353 isWriting = ERROR;
355 else
357 isWriting = 0;
360 if(consoleFlags & ERROR)
362 std::cerr << msg;
365 if(loggingFlags & ERROR)
367 assert(Out::logFile != 0);
368 const char *logMsg = msg.c_str();
369 fwrite(logMsg, std::strlen(logMsg), sizeof(char), Out::logFile);
370 fflush(Out::logFile);
374 void
375 Out::warningPrinter(std::string msg)
377 if (!(consoleFlags & WARNING) && !(loggingFlags & WARNING))
378 return;
380 // If another command didn't finish its line, fix it for it
381 if((isWriting | WARNING) != WARNING)
383 std::cerr << std::endl;
384 isWriting = 0;
385 debug << "Printed an unfinished line" << endl;
388 // Only write prefix one time per line
389 if((isWriting & WARNING) == 0)
391 msg = "WARNING: " + msg;
394 // If msg is a finished line reset flags, else set flags
395 if(msg.find('\n') == std::string::npos)
397 isWriting = WARNING;
399 else
401 isWriting = 0;
404 if(consoleFlags & WARNING)
406 std::cerr << msg;
409 if(loggingFlags & WARNING)
411 assert(Out::logFile != 0);
412 const char *logMsg = msg.c_str();
413 fwrite(logMsg, std::strlen(logMsg), sizeof(char), Out::logFile);
414 fflush(Out::logFile);
418 void
419 Out::msgPrinter(std::string msg)
421 // If another command didn't finish its line, fix it for it
422 if((isWriting | MSG) != MSG)
424 std::cerr << std::endl;
425 isWriting = 0;
426 debug << "Printed an unfinished line" << endl;
429 // If msg is a finished line reset flags, else set flags
430 if(msg.find('\n') == std::string::npos)
432 isWriting = MSG;
434 else
436 isWriting = 0;
439 std::cout << msg;
442 void
443 Out::debugPrinter(std::string msg)
445 if (!(consoleFlags & DEBUG) && !(loggingFlags & DEBUG))
446 return;
448 // If another command didn't finish its line, fix it for it
449 if((isWriting | DEBUG) != DEBUG)
451 std::cerr << std::endl;
452 isWriting = 0;
453 debug << "Printed an unfinished line" << endl;
456 // Only write prefix one time per line
457 if((isWriting & DEBUG) == 0)
459 msg = "DEBUG: " + msg;
462 // If msg is a finished line reset flags, else set flags
463 if(msg.find('\n') == std::string::npos)
465 isWriting = DEBUG;
467 else
469 isWriting = 0;
472 if(consoleFlags & DEBUG)
474 std::cerr << msg;
477 if(loggingFlags & DEBUG)
479 assert(Out::logFile != 0);
480 const char *logMsg = msg.c_str();
481 fwrite(logMsg, std::strlen(logMsg), sizeof(char), Out::logFile);
482 fflush(Out::logFile);