/*---------------------------------------------------------------------- | NPT_String::Format +---------------------------------------------------------------------*/ NPT_String NPT_String::Format(const char* format, ...) { NPT_String result; NPT_Size buffer_size = NPT_STRING_FORMAT_BUFFER_DEFAULT_SIZE; // default value va_list args; for(;;) { /* try to format (it might not fit) */ result.Reserve(buffer_size); char* buffer = result.UseChars(); va_start(args, format); int f_result = NPT_FormatStringVN(buffer, buffer_size, format, args); va_end(args); if (f_result >= (int)(buffer_size)) f_result = -1; if (f_result >= 0) { result.SetLength(f_result); break; } /* the buffer was too small, try something bigger */ /* (we don't trust the return value of NPT_FormatStringVN */ /* for the actual size needed) */ buffer_size *= 2; if (buffer_size > NPT_STRING_FORMAT_BUFFER_MAX_SIZE) break; } return result; }
/*---------------------------------------------------------------------- | NPT_Logger::Log +---------------------------------------------------------------------*/ void NPT_Logger::Log(int level, const char* source_file, unsigned int source_line, const char* source_function, const char* msg, ...) { // this is a no-op if the log manager is disabled if (!LogManager.IsEnabled()) return; /* check the log level (in case filtering has not already been done) */ if (level < m_Level) return; // we need to disable the log manager while someone is logging NPT_LogManagerAutoDisabler autodisabler; /* format the message */ char buffer[NPT_LOG_STACK_BUFFER_MAX_SIZE]; NPT_Size buffer_size = sizeof(buffer); char* message = buffer; int result; va_list args; for(;;) { /* try to format the message (it might not fit) */ va_start(args, msg); result = NPT_FormatStringVN(message, buffer_size-1, msg, args); va_end(args); if (result >= (int)(buffer_size-1)) result = -1; message[buffer_size-1] = 0; /* force a NULL termination */ if (result >= 0) break; /* the buffer was too small, try something bigger */ buffer_size = (buffer_size+NPT_LOG_HEAP_BUFFER_INCREMENT)*2; if (buffer_size > NPT_LOG_HEAP_BUFFER_MAX_SIZE) break; if (message != buffer) delete[] message; message = new char[buffer_size]; if (message == NULL) return; } /* the message is formatted, publish it to the handlers */ NPT_LogRecord record; NPT_Logger* logger = this; /* setup the log record */ record.m_LoggerName = logger->m_Name, record.m_Level = level; record.m_Message = message; record.m_SourceFile = source_file; record.m_SourceLine = source_line; record.m_SourceFunction = source_function; NPT_System::GetCurrentTimeStamp(record.m_TimeStamp); record.m_ThreadId = NPT_Thread::GetCurrentThreadId(); /* call all handlers for this logger and parents */ m_Manager.Lock(); while (logger) { /* call all handlers for the current logger */ for (NPT_List<NPT_LogHandler*>::Iterator i = logger->m_Handlers.GetFirstItem(); i; ++i) { NPT_LogHandler* handler = *i; handler->Log(record); } /* forward to the parent unless this logger does not forward */ if (logger->m_ForwardToParent) { logger = logger->m_Parent; } else { break; } } m_Manager.Unlock(); /* free anything we may have allocated */ if (message != buffer) delete[] message; }