PetaVision  Alpha
PVLog.cpp
1 #include "utils/PVLog.hpp"
2 #include "io/io.hpp" // expandLeadingTilde
3 #include <fstream>
4 #include <libgen.h>
5 #include <stdarg.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 
10 namespace PV {
11 
12 template <typename T>
14  public:
15  LogFileStream(std::basic_ostream<T> &st) : mDefaultStream(st) { setStreamDefault(); }
16  virtual ~LogFileStream() {
17  if (mCreatedWithNew) {
18  delete mStream;
19  }
20  }
21 
22  std::basic_ostream<T> &getStream() { return *mStream; }
23  void setStream(char const *path, std::ios_base::openmode mode = std::ios_base::out) {
24  if (mCreatedWithNew) {
25  delete mStream;
26  }
27  if (path) {
28  char *realPath = strdup(expandLeadingTilde(path).c_str());
29  if (realPath == nullptr) {
30  // Error message has to go to cerr and not Fatal() because Fatal uses LogFileStream.
31  std::cerr << "LogFileStream::setStream failed for \"" << realPath << "\"\n";
32  exit(EXIT_FAILURE);
33  }
34  mStream = new std::basic_ofstream<T>(realPath, mode);
35  if (mStream->fail() || mStream->fail()) {
36  // Error message has to go to cerr and not Fatal() because Fatal uses setLogStream.
37  std::cerr << "Unable to open logFile \"" << path << "\"." << std::endl;
38  exit(EXIT_FAILURE);
39  }
40  mCreatedWithNew = true;
41  free(realPath);
42  }
43  else {
44  mStream = &mDefaultStream;
45  mCreatedWithNew = false;
46  }
47  }
48  void setStream(std::basic_ostream<T> *stream) {
49  if (mCreatedWithNew) {
50  delete mStream;
51  }
52  mStream = stream;
53  mCreatedWithNew = false;
54  }
55  void setStreamDefault() {
56  if (mCreatedWithNew) {
57  delete mStream;
58  }
59  mStream = &mDefaultStream;
60  mCreatedWithNew = false;
61  }
62 
63  private:
64  std::basic_ostream<T> &mDefaultStream;
65  std::basic_ostream<T> *mStream = nullptr;
66  bool mCreatedWithNew = false;
67 };
68 
69 LogFileStream<char> errorLogFileStream(std::cerr);
70 LogFileStream<char> outputLogFileStream(std::cout);
71 LogFileStream<wchar_t> errorLogFileWStream(std::wcerr);
72 LogFileStream<wchar_t> outputLogFileWStream(std::wcout);
73 
74 std::ostream &getErrorStream() { return errorLogFileStream.getStream(); }
75 std::ostream &getOutputStream() { return outputLogFileStream.getStream(); }
76 
77 std::wostream &getWErrorStream() { return errorLogFileWStream.getStream(); }
78 std::wostream &getWOutputStream() { return outputLogFileWStream.getStream(); }
79 
80 void setLogFile(std::string const &logFile, std::ios_base::openmode mode) {
81  if (!logFile.empty()) {
82  setLogFile(logFile.c_str(), mode);
83  }
84 }
85 
86 void setLogFile(char const *logFile, std::ios_base::openmode mode) {
87  outputLogFileStream.setStream(logFile, mode);
88  if (logFile) {
89  errorLogFileStream.setStream(&getOutputStream());
90  }
91  else {
92  errorLogFileStream.setStream(logFile, mode);
93  }
94 }
95 
96 void setWLogFile(std::wstring const &logFile, std::ios_base::openmode mode) {
97  if (!logFile.empty()) {
98  setWLogFile(logFile.c_str(), mode);
99  }
100 }
101 
102 void setWLogFile(char const *logFile, std::ios_base::openmode mode) {
103  outputLogFileWStream.setStream(logFile, mode);
104  if (logFile) {
105  errorLogFileWStream.setStream(&getWOutputStream());
106  }
107  else {
108  errorLogFileWStream.setStream(logFile, mode);
109  }
110 }
111 
112 } // end namespace PV