class LogStream : public Stream { #ifdef PLATFORM_WIN32 HANDLE hfile; #endif #ifdef PLATFORM_POSIX enum { INVALID_HANDLE_VALUE = -1 }; int hfile; #endif CriticalSection cs; char filename[512]; char backup[512]; byte buffer[512]; int filesize; byte *p; int sizelimit; int part; void Flush(); void Put0(int w); protected: virtual void _Put(int w); virtual void _Put(const void *data, dword size); virtual int64 GetSize() const { return filesize; } public: virtual bool IsOpen() const; void Create(const char *path, bool append); void SetLimit(int maxsize) { sizelimit = maxsize; } bool Delete(); void Close(); LogStream(); ~LogStream(); }; void ActivateUsrLog(); void ActivatePersistentUsrLog(); bool IsUsrLog(); Stream& UsrLog(); Stream& UsrLog(const char *line); Stream& UsrLogT(const char *line); Stream& UsrLogT(int indent, const char *line); void DeleteUsrLog(); Stream& BugLog(); Stream& StdLog(); Stream& VppLog(); void SetVppLog(Stream& log); void SetVppLogName(const String& file); void SetVppLogSizeLimit(int filesize); void SetVppLogNoDeleteOnStartup(); void HexDump(Stream& s, const void *ptr, int size, int maxsize = INT_MAX); int msecs(int from = 0); String GetTypeName(const char *type_name); inline String GetTypeName(const ::std::type_info& tinfo) { return GetTypeName(tinfo.name()); } void __LOGF__(const char *format, ...); #ifdef _DEBUG #define _DBG_ #define DEBUGCODE(x) x #define LOG(a) UPP::VppLog() << a << '\n' #define LOGF UPP::__LOGF__ #define LOGBEGIN() UPP::VppLog().Begin() #define LOGEND() UPP::VppLog().End() #define LOGBLOCK(n) RLOGBLOCK(n) #define LOGHEXDUMP(s, a) UPP::HexDump(VppLog(), s, a) #define QUOTE(a) { LOG(#a); a; } #define LOGSRCPOS() UPP::VppLog() << __FILE__ << '#' << __LINE__ << '\n' #define DUMP(a) UPP::VppLog() << #a << " = " << (a) << '\n' #define DUMPC(c) UPP::DumpContainer(VppLog() << #c << ":\n", (c)) #define DUMPCC(c) UPP::DumpContainer2(VppLog() << #c << ":\n", (c)) #define DUMPCCC(c) UPP::DumpContainer3(VppLog() << #c << ":\n", (c)) #define XASSERT(c, d) if(!bool(c)) { LOG("XASSERT failed"); LOGSRCPOS(); LOG(d); ASSERT(0); } else #define NEVER() ASSERT(0) #define XNEVER(d) if(1) { LOG("NEVER failed"); LOGSRCPOS(); LOG(d); ASSERT(0); } else #define CHECK(c) if(!bool(c)) { ASSERT(0); } else #define XCHECK(c, d) if(!bool(c)) { LOG("XCHECK failed"); LOGSRCPOS(); LOG(d); ASSERT(0); } else #define TIMING(x) RTIMING(x) #define HITCOUNT(x) RHITCOUNT(x) #define ACTIVATE_TIMING() UPP::TimingInspector::Activate(true); #define DEACTIVATE_TIMING() UPP::TimingInspector::Activate(false); #define DLOG(x) LOG(x) #define DDUMP(x) DUMP(x) #define DDUMPC(x) DUMPC(x) #else #define DLOG(x) @@@ERROR!!! #define DDUMP(x) @@@ERROR!!! #define DDUMPC(x) @@@ERROR!!! #define ASSERT(x) #define DEBUGCODE(x) inline void LOGF(const char *format, ...) {} #define LOG(a) #define LOGBEGIN() #define LOGEND() #define LOGBLOCK(n) #define LOGHEXDUMP(s, a) #define QUOTE(a) a #define LOGSRCPOS() #define DUMP(a) #define DUMPC(a) #define DUMPCC(a) #define DUMPCCC(a) #define XASSERT(c, d) #define NEVER() #define XNEVER(d) #define CHECK(c) (c) #define XCHECK(c, d) (c) #define TIMING(x) #define HITCOUNT(x) #define ACTIVATE_TIMING() #define DEACTIVATE_TIMING() #endif struct DebugLogBlock { DebugLogBlock(const char *name) : name(name) { VppLog() << name << "\n" << BeginIndent; } ~DebugLogBlock() { VppLog() << EndIndent << "//" << name << "\n"; } const char *name; }; #define RLOG(a) UPP::VppLog() << a << '\n' #define RLOGBEGIN() UPP::VppLog().Begin() #define RLOGEND() UPP::VppLog().End() #define RLOGBLOCK(n) UPP::DebugLogBlock MK__s(n) #define RLOGHEXDUMP(s, a) UPP::HexDump(UPP::VppLog(), s, a) #define RQUOTE(a) { LOG(#a); a; } #define RLOGSRCPOS() UPP::VppLog() << __FILE__ << '#' << __LINE__ << '\n' #define RDUMP(a) UPP::VppLog() << #a << " = " << (a) << '\n' #define RDUMPC(c) UPP::DumpContainer(UPP::VppLog() << #c << ":\n", (c)) // Crash support void InstallCrashDump(const char *app_info = NULL); // Dumping templates template void DumpContainer(Stream& s, T ptr, T end) { int i = 0; s.Begin(); while(ptr != end) s << '[' << i++ << "] = " << *ptr++ << '\n'; s.End(); } template void DumpContainer(Stream& s, const C& c) { DumpContainer(s, c.Begin(), c.End()); } template void DumpContainer2(Stream& s, T ptr, T end) { int i = 0; s.Begin(); while(ptr != end) { s << '[' << i++ << "] =\n"; DumpContainer(s, (*ptr).Begin(), (*ptr).End()); ptr++; } s.End(); } template void DumpContainer2(Stream& s, const C& c) { DumpContainer2(s, c.Begin(), c.End()); } template void DumpContainer3(Stream& s, T ptr, T end) { int i = 0; s.Begin(); while(ptr != end) { s << '[' << i++ << "] =\n"; DumpContainer2(s, (*ptr).Begin(), (*ptr).End()); ptr++; } s.End(); } template void DumpContainer3(Stream& s, const C& c) { DumpContainer3(s, c.Begin(), c.End()); }