![]() |
Shadowrun: Awakened 29 September 2011 - Build 871
|
00001 /* 00002 Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved. 00003 00004 Redistribution and use in source and binary forms, with or without 00005 modification, are permitted provided that the following conditions are met: 00006 00007 * Redistributions of source code must retain the above copyright notice, 00008 this list of conditions and the following disclaimer. 00009 * Redistributions in binary form must reproduce the above copyright notice, 00010 this list of conditions and the following disclaimer in the documentation 00011 and/or other materials provided with the distribution. 00012 * Neither the name of LibCat nor the names of its contributors may be used 00013 to endorse or promote products derived from this software without 00014 specific prior written permission. 00015 00016 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00017 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00018 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00019 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 00020 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00021 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00022 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00023 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00024 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00025 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00026 POSSIBILITY OF SUCH DAMAGE. 00027 */ 00028 00029 #ifndef CAT_LOGGING_HPP 00030 #define CAT_LOGGING_HPP 00031 00032 #include <cat/threads/RegionAllocator.hpp> 00033 00034 #if defined(CAT_OS_WINDOWS) 00035 #include <cat/port/WindowsInclude.hpp> 00036 #endif 00037 00038 namespace cat { 00039 00040 00042 00043 enum EventSeverity 00044 { 00045 LVL_INANE, 00046 LVL_INFO, 00047 LVL_WARN, 00048 LVL_OOPS, 00049 LVL_FATAL, 00050 00051 LVL_SILENT, // invalid for an actual event's level, valid value for a threshold 00052 }; 00053 00054 00056 00057 region_string HexDumpString(const void *vdata, u32 bytes); 00058 00059 // Write to console (and debug log in windows) then trigger a breakpoint and exit 00060 void FatalStop(const char *message); 00061 00062 void DefaultLogCallback(EventSeverity severity, const char *source, region_ostringstream &msg); 00063 00064 00066 00067 typedef void (*LogCallback)(EventSeverity severity, const char *source, region_ostringstream &msg); 00068 00069 class Logging : public Singleton<Logging> 00070 { 00071 CAT_SINGLETON(Logging); 00072 00073 LogCallback _callback; 00074 00075 friend class Recorder; 00076 void LogEvent(Recorder *recorder); 00077 00078 public: 00079 int _log_threshold; 00080 00081 public: 00082 void Initialize(EventSeverity min_severity = LVL_INANE); 00083 CAT_INLINE void SetThreshold(EventSeverity min_severity) { _log_threshold = min_severity; } 00084 void ReadSettings(); 00085 void Shutdown(); 00086 00087 protected: 00088 bool _service; 00089 #if defined(CAT_OS_WINDOWS) 00090 HANDLE _event_source; 00091 #endif 00092 00093 public: 00094 CAT_INLINE bool IsService() { return _service; } 00095 void EnableServiceMode(const char *service_name); 00096 void WriteServiceLog(EventSeverity severity, const char *line); 00097 00098 public: 00099 // Not thread-safe 00100 CAT_INLINE void SetLogCallback(LogCallback cb) { _callback = cb; } 00101 }; 00102 00103 00105 00106 class Recorder 00107 { 00108 friend class Logging; 00109 EventSeverity _severity; 00110 const char *_subsystem; 00111 region_ostringstream _msg; 00112 00113 public: 00114 Recorder(const char *subsystem, EventSeverity severity); 00115 ~Recorder(); 00116 00117 public: 00118 template<class T> inline Recorder &operator<<(const T &t) 00119 { 00120 _msg << t; 00121 return *this; 00122 } 00123 }; 00124 00125 // Because there is an IF statement in the macro, you cannot use the 00126 // braceless if-else construction: 00127 // if (XYZ) WARN("SS") << "ERROR!"; else INFO("SS") << "OK!"; <-- bad 00128 // Instead use: 00129 // if (XYZ) { WARN("SS") << "ERROR!"; } else INFO("SS") << "OK!"; <-- good 00130 #define RECORD(subsystem, severity) \ 00131 if (severity >= Logging::ii->_log_threshold) Recorder(subsystem, severity) 00132 00133 #define INANE(subsystem) RECORD(subsystem, LVL_INANE) 00134 #define INFO(subsystem) RECORD(subsystem, LVL_INFO) 00135 #define WARN(subsystem) RECORD(subsystem, LVL_WARN) 00136 #define OOPS(subsystem) RECORD(subsystem, LVL_OOPS) 00137 #define FATAL(subsystem) RECORD(subsystem, LVL_FATAL) 00138 00139 00141 00142 class Enforcer 00143 { 00144 protected: 00145 std::ostringstream oss; 00146 00147 public: 00148 Enforcer(const char *locus); 00149 ~Enforcer(); 00150 00151 public: 00152 template<class T> inline Enforcer &operator<<(const T &t) 00153 { 00154 oss << t; 00155 return *this; 00156 } 00157 }; 00158 00159 00160 #define USE_ENFORCE_EXPRESSION_STRING 00161 #define USE_ENFORCE_FILE_LINE_STRING 00162 00163 00164 #if defined(USE_ENFORCE_EXPRESSION_STRING) 00165 # define ENFORCE_EXPRESSION_STRING(exp) "Failed assertion (" #exp ")" 00166 #else 00167 # define ENFORCE_EXPRESSION_STRING(exp) "Failed assertion" 00168 #endif 00169 00170 #if defined(USE_ENFORCE_FILE_LINE_STRING) 00171 # define ENFORCE_FILE_LINE_STRING " at " __FILE__ ":" CAT_STRINGIZE(__LINE__) 00172 #else 00173 # define ENFORCE_FILE_LINE_STRING "" 00174 #endif 00175 00176 // Because there is an IF statement in the macro, you cannot use the 00177 // braceless if-else construction: 00178 // if (XYZ) ENFORCE(A == B) << "ERROR"; else INFO("SS") << "OK"; <-- bad! 00179 // Instead use: 00180 // if (XYZ) { ENFORCE(A == B) << "ERROR"; } else INFO("SS") << "OK"; <-- good! 00181 00182 #define ENFORCE(exp) if ( (exp) == 0 ) Enforcer(ENFORCE_EXPRESSION_STRING(exp) ENFORCE_FILE_LINE_STRING "\n") 00183 #define EXCEPTION() Enforcer("Exception" ENFORCE_FILE_LINE_STRING "\n") 00184 00185 #if defined(CAT_DEBUG) 00186 # define DEBUG_ENFORCE(exp) ENFORCE(exp) 00187 #else 00188 # define DEBUG_ENFORCE(exp) if (0) ENFORCE(exp) /* hopefully will be optimized out of existence */ 00189 #endif 00190 00191 00192 } // namespace cat 00193 00194 #endif // CAT_LOGGING_HPP
Copyright © 2007-2010 by The Shadowrun: Awakened Team. This work is licensed under the GNU Lesser General Public License 3.