📄 osblog.cpp
字号:
/*********************************************************************** *********************************************************************** * * $Id: OSBlog.cpp,v 1.1.2.7 2001/10/09 22:04:53 jerry Exp $ * * Implementation of the OSBlog functions defined in OSBlog.h, see * that header for details * *********************************************************************** **********************************************************************//****************License************************************************ * * Copyright 2000-2001. SpeechWorks International, Inc. * * Use of this software is subject to notices and obligations set forth * in the SpeechWorks Public License - Software Version 1.1 which is * included with this software. * * SpeechWorks is a registered trademark, and SpeechWorks Here, * DialogModules and the SpeechWorks logo are trademarks of SpeechWorks * International, Inc. in the United States and other countries. * ************************************************************************/static const char *rcsid = 0 ? (char *) &rcsid :"$Id: OSBlog.cpp,v 1.1.2.7 2001/10/09 22:04:53 jerry Exp $";// -----1=0-------2=0-------3=0-------4=0-------5=0-------6=0-------7=0-------8#include <cstdio>#include <cstring> // For memset()#include <ctime> // For time_t#include <ctype.h> // For isspace()#include <wctype.h> // For iswalpha()#ifdef WIN32#define WIN32_LEAN_AND_MEAN#include <windows.h>#include <sys/timeb.h> // For _ftime()#else#include <time.h> // For gettimeofday()#include <sys/time.h>#include <unistd.h>#endif#define OSBLOG_EXPORTS#include "OSBlog.h" // Header for these functions#include "VXItrd.h" // for VXItrdMutex#include "SBlogOSUtils.h"#define MAX_LOG_BUFFER 4096#ifndef MODULE_PREFIX#define MODULE_PREFIX COMPANY_DOMAIN L"."#endif// Global variablesstatic bool gblInitialized = false;static VXItrdMutex *gblLogMutex = NULL;static FILE *gblLogFile = NULL;static bool gblLogToStdout = false;// Convert wide to narrow characters#define w2c(w) (((w) & 0xff00)?'\277':((unsigned char) ((w) & 0x00ff)))/**********************************************************************/// Log utility classes/**********************************************************************/const VXIint SEP_LEN = 1;const VXIchar KEY_SEP = L'=';const VXIchar ENTRY_SEP = L'|';const VXIchar ESCAPE = L'\\';class LogEntry {public: LogEntry(); virtual ~LogEntry() {} VXIlogResult Append(const VXIchar*, VXIunsigned n); VXIlogResult AppendVa(const VXIchar *format, va_list args); VXIlogResult AppendKeyValueVa(const VXIchar *format, va_list args); void operator+= (const VXIchar *val) { Append(val, 0); } void operator+= (const VXIchar val){ if(cur_size_ < MAX_LOG_BUFFER){ entry_[cur_size_++] = val; } entry_[cur_size_]=L'\0'; return ; } void operator+= (const char*); void operator+= (long int); void operator+= (VXIint32); void operator+= (VXIunsigned); void AddKeySep(){ (*this) += KEY_SEP; } void AddEntrySep(){ (*this) += ENTRY_SEP; } void Terminate() { if(cur_size_ == MAX_LOG_BUFFER) cur_size_--; entry_[cur_size_++] ='\n'; entry_[cur_size_] = '\0'; } const wchar_t *Entry()const {return entry_;} VXIunsigned size() const { return cur_size_; };protected: unsigned int cur_size_; wchar_t entry_[MAX_LOG_BUFFER+1];};LogEntry::LogEntry() : cur_size_(0){ time_t timestamp; VXIunsigned timestampMsec; char timestampStr[128]; SBlogGetTime (×tamp, ×tampMsec); SBlogGetTimeStampStr(timestamp,timestampMsec,timestampStr); (*this) += timestampStr; long userTime; long kernelTime; SBlogGetCPUTimes(&userTime,&kernelTime); this->AddEntrySep(); (*this) += "TUCPU"; this->AddKeySep(); (*this) += userTime; this->AddEntrySep(); (*this) += "TKCPU"; this->AddKeySep(); (*this) += kernelTime;}VXIlogResultLogEntry::Append (const VXIchar* val, VXIunsigned n){ unsigned int i = 0; if (n <= 0) n = wcslen(val); // strip leading and trailing whitespace while ((n > 0) && (iswspace(val[n-1]))) n--; while ((i < n) && (iswspace(val[i]))) i++; while((cur_size_ < MAX_LOG_BUFFER) && (i < n)){ if (iswspace(val[i])) { entry_[cur_size_++] = L' '; } else { if ((val[i] == KEY_SEP) || (val[i] == ENTRY_SEP) || (val[i] == ESCAPE)) entry_[cur_size_++] = ESCAPE; entry_[cur_size_++] = val[i]; } i++; } entry_[cur_size_]=L'\0'; return VXIlog_RESULT_SUCCESS;}VXIlogResult LogEntry::AppendVa(const VXIchar *format, va_list args){ if (! format) return VXIlog_RESULT_SUCCESS; SBlogVswprintf(&entry_[cur_size_], MAX_LOG_BUFFER - cur_size_, format, args); cur_size_ += wcslen(&entry_[cur_size_]); return VXIlog_RESULT_SUCCESS;}VXIlogResult LogEntry::AppendKeyValueVa(const VXIchar *format, va_list args){ if (! format) return VXIlog_RESULT_SUCCESS; // First create a modified format string that will properly delimit // the key/value pairs VXIlogResult rc = VXIlog_RESULT_SUCCESS; bool hadFreeformText = false; int replacementStart = -1, fieldCount = 0; size_t resultFormatLen = 0; VXIchar resultFormat[MAX_LOG_BUFFER]; resultFormat[0] = L'\0'; for (int i = 0; (format[i] != L'\0') && (rc == VXIlog_RESULT_SUCCESS); i++) { if (format[i] == '%') { if (replacementStart > -1) replacementStart = -1; // double %% else replacementStart = i; } else if ((replacementStart > -1) && (iswalpha(format[i])) && (format[i] != L'l') && (format[i] != L'L') && (format[i] != L'h')) { if ((fieldCount % 2 == 0) && (format[i] != L's') && (format[i] != L'S')) { // Keys must be a %s or %S, truncate from here rc = VXIlog_RESULT_NON_FATAL_ERROR; } else { // Insert the replacement expression and the seperator int index = resultFormatLen; resultFormatLen += (i - replacementStart) + 1 + SEP_LEN; if (resultFormatLen < MAX_LOG_BUFFER) { wcsncpy(&resultFormat[index], &format[replacementStart], (i - replacementStart) + 1); index += (i - replacementStart) + 1; if (fieldCount % 2 == 0) resultFormat[index++] = KEY_SEP; else if (format[i + 1] != L'\0') resultFormat[index++] = ENTRY_SEP; resultFormat[index] = L'\0'; } else { // Overflow, truncate the format string from here rc = VXIlog_RESULT_NON_FATAL_ERROR; } replacementStart = -1; fieldCount++; } } else if (replacementStart == -1) { // Shouldn't have free-form text, skip it. Proceeding allows us // to gracefully handle things like "%s0x%p". hadFreeformText = true; } } // if key/value is not even truncate the field and return an error, // but proceed with the other fields. If there was free form text, // we skipped it and return an error, but proceed with logging. if (fieldCount % 2 != 0) { rc = VXIlog_RESULT_NON_FATAL_ERROR; fieldCount--; } else if (hadFreeformText) { rc = VXIlog_RESULT_NON_FATAL_ERROR; } // Now create the final output SBlogVswprintf(&entry_[cur_size_], MAX_LOG_BUFFER - cur_size_, resultFormat, args); cur_size_ += wcslen(&entry_[cur_size_]); return rc;}void LogEntry::operator+= (const char* val){ unsigned int i = 0; unsigned int n = strlen(val); // strip leading and trailing whitespace while ((n > 0) && (isspace(val[n-1]))) n--; while ((i < n) && (isspace(val[i]))) i++; while((cur_size_ < MAX_LOG_BUFFER) && (i < n)){ if (isspace(val[i])) { entry_[cur_size_++] = L' '; } else { if ((val[i] == KEY_SEP) || (val[i] == ENTRY_SEP) || (val[i] == ESCAPE)) entry_[cur_size_++] = ESCAPE; entry_[cur_size_++] = (VXIchar) val[i]; } i++; } entry_[cur_size_]=L'\0'; return ;}voidLogEntry::operator+= (VXIint32 val){ // how can temp be made the right size to start? char temp[128]; sprintf(temp,"%d",val); (*this) += temp; return ;}voidLogEntry::operator+= (long int val){ // how can temp be made the right size to start? char temp[128]; sprintf(temp,"%ld",val); (*this) += temp; return ;}voidLogEntry::operator+= (VXIunsigned val){ char temp[128]; sprintf(temp,"%d",val); (*this) += temp; return ;}/**********************************************************************/// Logging class/**********************************************************************/struct myAPI { OSBlogInterface intf; void *impl_;};class OSBlog {public: OSBlog(VXIint channelNum); ~OSBlog(); bool DiagnosticIsEnabled(VXIunsigned tagID); VXIlogResult DiagnosticLog(VXIunsigned tagID, const VXIchar* subtag, const VXIchar* format, va_list args); VXIlogResult EventLog(VXIunsigned eventID, const VXIchar* format, va_list args); VXIlogResult ErrorLog(const VXIchar* moduleName, VXIunsigned errorID, const VXIchar* format, va_list args); VXIlogResult ControlDiagnosticTag(VXIunsigned tagID, VXIbool state);private:private: // Internal methods static unsigned testbit(unsigned char num, int bitpos); static void setbit(unsigned char *num, int bitpos); static void clearbit(unsigned char *num, int bitpos); int Convert2Index(VXIunsigned tagID, VXIunsigned *index, VXIunsigned *bit_pos) const; VXIlogResult WriteEntry(const LogEntry &entry, bool logToStdout = true);protected: VXIint channelNum; VXItrdMutex *callbackLock; unsigned char TagIDs[LOG_MAX_TAG];};OSBlog::OSBlog(VXIint chNum) : channelNum(chNum){ // reset TAG ID range memset(TagIDs,0,LOG_MAX_TAG); VXItrdMutexCreate(&callbackLock); }OSBlog::~OSBlog() { VXItrdMutexDestroy(&callbackLock);}/** * testbit * testbit returns the value of the given bit * 1 is set, 0 is clear */unsigned OSBlog::testbit(unsigned char num, int bitpos){ return (num >> bitpos) & ~(~0 << 1); }/** * setbit sets a given bit */void OSBlog::setbit(unsigned char *num, int bitpos){ *num |= (1 << bitpos);}/** * clearbit clears a given bit */void OSBlog::clearbit(unsigned char *num, int bitpos){ *num &= ~(1 << bitpos);}int OSBlog::Convert2Index(VXIunsigned tagID, VXIunsigned *index, VXIunsigned *bit_pos) const{ if (tagID < 0) return 0; // retrieving index for char array *index = tagID/8; // 8 bits per char // check for overflow TAG ID if (*index >= LOG_MAX_TAG) return 0; // retrieving bit position (bit range from 0-7) *bit_pos = tagID%7; return 1; // done}VXIlogResult OSBlog::ControlDiagnosticTag(VXIunsigned tagID, VXIbool state){ VXIunsigned bindex, bpos; if(!Convert2Index(tagID, &bindex, &bpos)) return VXIlog_RESULT_INVALID_ARGUMENT;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -