vrshoot
diff libs/assimp/DefaultLogger.cpp @ 0:b2f14e535253
initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 01 Feb 2014 19:58:19 +0200 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/libs/assimp/DefaultLogger.cpp Sat Feb 01 19:58:19 2014 +0200 1.3 @@ -0,0 +1,423 @@ 1.4 +/* 1.5 +--------------------------------------------------------------------------- 1.6 +Open Asset Import Library (assimp) 1.7 +--------------------------------------------------------------------------- 1.8 + 1.9 +Copyright (c) 2006-2012, assimp team 1.10 + 1.11 +All rights reserved. 1.12 + 1.13 +Redistribution and use of this software in source and binary forms, 1.14 +with or without modification, are permitted provided that the following 1.15 +conditions are met: 1.16 + 1.17 +* Redistributions of source code must retain the above 1.18 + copyright notice, this list of conditions and the 1.19 + following disclaimer. 1.20 + 1.21 +* Redistributions in binary form must reproduce the above 1.22 + copyright notice, this list of conditions and the 1.23 + following disclaimer in the documentation and/or other 1.24 + materials provided with the distribution. 1.25 + 1.26 +* Neither the name of the assimp team, nor the names of its 1.27 + contributors may be used to endorse or promote products 1.28 + derived from this software without specific prior 1.29 + written permission of the assimp team. 1.30 + 1.31 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.32 +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.33 +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.34 +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1.35 +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.36 +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.37 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.38 +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.39 +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.40 +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.41 +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.42 +--------------------------------------------------------------------------- 1.43 +*/ 1.44 + 1.45 +/** @file DefaultLogger.cpp 1.46 + * @brief Implementation of DefaultLogger (and Logger) 1.47 + */ 1.48 + 1.49 +#include "AssimpPCH.h" 1.50 +#include "DefaultIOSystem.h" 1.51 + 1.52 +// Default log streams 1.53 +#include "Win32DebugLogStream.h" 1.54 +#include "StdOStreamLogStream.h" 1.55 +#include "FileLogStream.h" 1.56 + 1.57 +#ifndef ASSIMP_BUILD_SINGLETHREADED 1.58 +# include <boost/thread/thread.hpp> 1.59 +# include <boost/thread/mutex.hpp> 1.60 + 1.61 +boost::mutex loggerMutex; 1.62 +#endif 1.63 + 1.64 +namespace Assimp { 1.65 + 1.66 +// ---------------------------------------------------------------------------------- 1.67 +NullLogger DefaultLogger::s_pNullLogger; 1.68 +Logger *DefaultLogger::m_pLogger = &DefaultLogger::s_pNullLogger; 1.69 + 1.70 +static const unsigned int SeverityAll = Logger::Info | Logger::Err | Logger::Warn | Logger::Debugging; 1.71 + 1.72 +// ---------------------------------------------------------------------------------- 1.73 +// Represents a log-stream + its error severity 1.74 +struct LogStreamInfo 1.75 +{ 1.76 + unsigned int m_uiErrorSeverity; 1.77 + LogStream *m_pStream; 1.78 + 1.79 + // Constructor 1.80 + LogStreamInfo( unsigned int uiErrorSev, LogStream *pStream ) : 1.81 + m_uiErrorSeverity( uiErrorSev ), 1.82 + m_pStream( pStream ) 1.83 + { 1.84 + // empty 1.85 + } 1.86 + 1.87 + // Destructor 1.88 + ~LogStreamInfo() 1.89 + { 1.90 + delete m_pStream; 1.91 + } 1.92 +}; 1.93 + 1.94 +// ---------------------------------------------------------------------------------- 1.95 +// Construct a default log stream 1.96 +LogStream* LogStream::createDefaultStream(aiDefaultLogStream streams, 1.97 + const char* name /*= "AssimpLog.txt"*/, 1.98 + IOSystem* io /*= NULL*/) 1.99 +{ 1.100 + switch (streams) 1.101 + { 1.102 + // This is a platform-specific feature 1.103 + case aiDefaultLogStream_DEBUGGER: 1.104 +#ifdef WIN32 1.105 + return new Win32DebugLogStream(); 1.106 +#else 1.107 + return NULL; 1.108 +#endif 1.109 + 1.110 + // Platform-independent default streams 1.111 + case aiDefaultLogStream_STDERR: 1.112 + return new StdOStreamLogStream(std::cerr); 1.113 + case aiDefaultLogStream_STDOUT: 1.114 + return new StdOStreamLogStream(std::cout); 1.115 + case aiDefaultLogStream_FILE: 1.116 + return (name && *name ? new FileLogStream(name,io) : NULL); 1.117 + default: 1.118 + // We don't know this default log stream, so raise an assertion 1.119 + ai_assert(false); 1.120 + 1.121 + }; 1.122 + 1.123 + // For compilers without dead code path detection 1.124 + return NULL; 1.125 +} 1.126 + 1.127 +// ---------------------------------------------------------------------------------- 1.128 +// Creates the only singleton instance 1.129 +Logger *DefaultLogger::create(const char* name /*= "AssimpLog.txt"*/, 1.130 + LogSeverity severity /*= NORMAL*/, 1.131 + unsigned int defStreams /*= aiDefaultLogStream_DEBUGGER | aiDefaultLogStream_FILE*/, 1.132 + IOSystem* io /*= NULL*/) 1.133 +{ 1.134 + // enter the mutex here to avoid concurrency problems 1.135 +#ifndef ASSIMP_BUILD_SINGLETHREADED 1.136 + boost::mutex::scoped_lock lock(loggerMutex); 1.137 +#endif 1.138 + 1.139 + if (m_pLogger && !isNullLogger() ) 1.140 + delete m_pLogger; 1.141 + 1.142 + m_pLogger = new DefaultLogger( severity ); 1.143 + 1.144 + // Attach default log streams 1.145 + // Stream the log to the MSVC debugger? 1.146 + if (defStreams & aiDefaultLogStream_DEBUGGER) 1.147 + m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_DEBUGGER)); 1.148 + 1.149 + // Stream the log to COUT? 1.150 + if (defStreams & aiDefaultLogStream_STDOUT) 1.151 + m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_STDOUT)); 1.152 + 1.153 + // Stream the log to CERR? 1.154 + if (defStreams & aiDefaultLogStream_STDERR) 1.155 + m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_STDERR)); 1.156 + 1.157 + // Stream the log to a file 1.158 + if (defStreams & aiDefaultLogStream_FILE && name && *name) 1.159 + m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_FILE,name,io)); 1.160 + 1.161 + return m_pLogger; 1.162 +} 1.163 + 1.164 +// ---------------------------------------------------------------------------------- 1.165 +void Logger::debug(const char* message) { 1.166 + 1.167 + // SECURITY FIX: otherwise it's easy to produce overruns since 1.168 + // sometimes importers will include data from the input file 1.169 + // (i.e. node names) in their messages. 1.170 + if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) { 1.171 + ai_assert(false); 1.172 + return; 1.173 + } 1.174 + return OnDebug(message); 1.175 +} 1.176 + 1.177 +// ---------------------------------------------------------------------------------- 1.178 +void Logger::info(const char* message) { 1.179 + 1.180 + // SECURITY FIX: see above 1.181 + if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) { 1.182 + ai_assert(false); 1.183 + return; 1.184 + } 1.185 + return OnInfo(message); 1.186 +} 1.187 + 1.188 +// ---------------------------------------------------------------------------------- 1.189 +void Logger::warn(const char* message) { 1.190 + 1.191 + // SECURITY FIX: see above 1.192 + if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) { 1.193 + ai_assert(false); 1.194 + return; 1.195 + } 1.196 + return OnWarn(message); 1.197 +} 1.198 + 1.199 +// ---------------------------------------------------------------------------------- 1.200 +void Logger::error(const char* message) { 1.201 + 1.202 + // SECURITY FIX: see above 1.203 + if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) { 1.204 + ai_assert(false); 1.205 + return; 1.206 + } 1.207 + return OnError(message); 1.208 +} 1.209 + 1.210 +// ---------------------------------------------------------------------------------- 1.211 +void DefaultLogger::set( Logger *logger ) 1.212 +{ 1.213 + // enter the mutex here to avoid concurrency problems 1.214 +#ifndef ASSIMP_BUILD_SINGLETHREADED 1.215 + boost::mutex::scoped_lock lock(loggerMutex); 1.216 +#endif 1.217 + 1.218 + if (!logger)logger = &s_pNullLogger; 1.219 + if (m_pLogger && !isNullLogger() ) 1.220 + delete m_pLogger; 1.221 + 1.222 + DefaultLogger::m_pLogger = logger; 1.223 +} 1.224 + 1.225 +// ---------------------------------------------------------------------------------- 1.226 +bool DefaultLogger::isNullLogger() 1.227 +{ 1.228 + return m_pLogger == &s_pNullLogger; 1.229 +} 1.230 + 1.231 +// ---------------------------------------------------------------------------------- 1.232 +// Singleton getter 1.233 +Logger *DefaultLogger::get() 1.234 +{ 1.235 + return m_pLogger; 1.236 +} 1.237 + 1.238 +// ---------------------------------------------------------------------------------- 1.239 +// Kills the only instance 1.240 +void DefaultLogger::kill() 1.241 +{ 1.242 + // enter the mutex here to avoid concurrency problems 1.243 +#ifndef ASSIMP_BUILD_SINGLETHREADED 1.244 + boost::mutex::scoped_lock lock(loggerMutex); 1.245 +#endif 1.246 + 1.247 + if (m_pLogger == &s_pNullLogger)return; 1.248 + delete m_pLogger; 1.249 + m_pLogger = &s_pNullLogger; 1.250 +} 1.251 + 1.252 +// ---------------------------------------------------------------------------------- 1.253 +// Debug message 1.254 +void DefaultLogger::OnDebug( const char* message ) 1.255 +{ 1.256 + if ( m_Severity == Logger::NORMAL ) 1.257 + return; 1.258 + 1.259 + char msg[MAX_LOG_MESSAGE_LENGTH*2]; 1.260 + ::sprintf(msg,"Debug, T%i: %s", GetThreadID(), message ); 1.261 + 1.262 + WriteToStreams( msg, Logger::Debugging ); 1.263 +} 1.264 + 1.265 +// ---------------------------------------------------------------------------------- 1.266 +// Logs an info 1.267 +void DefaultLogger::OnInfo( const char* message ) 1.268 +{ 1.269 + char msg[MAX_LOG_MESSAGE_LENGTH*2]; 1.270 + ::sprintf(msg,"Info, T%i: %s", GetThreadID(), message ); 1.271 + 1.272 + WriteToStreams( msg , Logger::Info ); 1.273 +} 1.274 + 1.275 +// ---------------------------------------------------------------------------------- 1.276 +// Logs a warning 1.277 +void DefaultLogger::OnWarn( const char* message ) 1.278 +{ 1.279 + char msg[MAX_LOG_MESSAGE_LENGTH*2]; 1.280 + ::sprintf(msg,"Warn, T%i: %s", GetThreadID(), message ); 1.281 + 1.282 + WriteToStreams( msg, Logger::Warn ); 1.283 +} 1.284 + 1.285 +// ---------------------------------------------------------------------------------- 1.286 +// Logs an error 1.287 +void DefaultLogger::OnError( const char* message ) 1.288 +{ 1.289 + char msg[MAX_LOG_MESSAGE_LENGTH*2]; 1.290 + ::sprintf(msg,"Error, T%i: %s", GetThreadID(), message ); 1.291 + 1.292 + WriteToStreams( msg, Logger::Err ); 1.293 +} 1.294 + 1.295 +// ---------------------------------------------------------------------------------- 1.296 +// Will attach a new stream 1.297 +bool DefaultLogger::attachStream( LogStream *pStream, unsigned int severity ) 1.298 +{ 1.299 + if (!pStream) 1.300 + return false; 1.301 + 1.302 + if (0 == severity) { 1.303 + severity = Logger::Info | Logger::Err | Logger::Warn | Logger::Debugging; 1.304 + } 1.305 + 1.306 + for ( StreamIt it = m_StreamArray.begin(); 1.307 + it != m_StreamArray.end(); 1.308 + ++it ) 1.309 + { 1.310 + if ( (*it)->m_pStream == pStream ) 1.311 + { 1.312 + (*it)->m_uiErrorSeverity |= severity; 1.313 + return true; 1.314 + } 1.315 + } 1.316 + 1.317 + LogStreamInfo *pInfo = new LogStreamInfo( severity, pStream ); 1.318 + m_StreamArray.push_back( pInfo ); 1.319 + return true; 1.320 +} 1.321 + 1.322 +// ---------------------------------------------------------------------------------- 1.323 +// Detatch a stream 1.324 +bool DefaultLogger::detatchStream( LogStream *pStream, unsigned int severity ) 1.325 +{ 1.326 + if (!pStream) 1.327 + return false; 1.328 + 1.329 + if (0 == severity) { 1.330 + severity = SeverityAll; 1.331 + } 1.332 + 1.333 + for ( StreamIt it = m_StreamArray.begin(); 1.334 + it != m_StreamArray.end(); 1.335 + ++it ) 1.336 + { 1.337 + if ( (*it)->m_pStream == pStream ) 1.338 + { 1.339 + (*it)->m_uiErrorSeverity &= ~severity; 1.340 + if ( (*it)->m_uiErrorSeverity == 0 ) 1.341 + { 1.342 + // don't delete the underlying stream 'cause the caller gains ownership again 1.343 + (**it).m_pStream = NULL; 1.344 + delete *it; 1.345 + m_StreamArray.erase( it ); 1.346 + break; 1.347 + } 1.348 + return true; 1.349 + } 1.350 + } 1.351 + return false; 1.352 +} 1.353 + 1.354 +// ---------------------------------------------------------------------------------- 1.355 +// Constructor 1.356 +DefaultLogger::DefaultLogger(LogSeverity severity) 1.357 + 1.358 + : Logger ( severity ) 1.359 + , noRepeatMsg (false) 1.360 + , lastLen( 0 ) 1.361 +{ 1.362 + lastMsg[0] = '\0'; 1.363 +} 1.364 + 1.365 +// ---------------------------------------------------------------------------------- 1.366 +// Destructor 1.367 +DefaultLogger::~DefaultLogger() 1.368 +{ 1.369 + for ( StreamIt it = m_StreamArray.begin(); it != m_StreamArray.end(); ++it ) { 1.370 + // also frees the underlying stream, we are its owner. 1.371 + delete *it; 1.372 + } 1.373 +} 1.374 + 1.375 +// ---------------------------------------------------------------------------------- 1.376 +// Writes message to stream 1.377 +void DefaultLogger::WriteToStreams(const char *message, 1.378 + ErrorSeverity ErrorSev ) 1.379 +{ 1.380 + ai_assert(NULL != message); 1.381 + 1.382 + // Check whether this is a repeated message 1.383 + if (! ::strncmp( message,lastMsg, lastLen-1)) 1.384 + { 1.385 + if (!noRepeatMsg) 1.386 + { 1.387 + noRepeatMsg = true; 1.388 + message = "Skipping one or more lines with the same contents\n"; 1.389 + } 1.390 + else return; 1.391 + } 1.392 + else 1.393 + { 1.394 + // append a new-line character to the message to be printed 1.395 + lastLen = ::strlen(message); 1.396 + ::memcpy(lastMsg,message,lastLen+1); 1.397 + ::strcat(lastMsg+lastLen,"\n"); 1.398 + 1.399 + message = lastMsg; 1.400 + noRepeatMsg = false; 1.401 + ++lastLen; 1.402 + } 1.403 + for ( ConstStreamIt it = m_StreamArray.begin(); 1.404 + it != m_StreamArray.end(); 1.405 + ++it) 1.406 + { 1.407 + if ( ErrorSev & (*it)->m_uiErrorSeverity ) 1.408 + (*it)->m_pStream->write( message); 1.409 + } 1.410 +} 1.411 + 1.412 +// ---------------------------------------------------------------------------------- 1.413 +// Returns thread id, if not supported only a zero will be returned. 1.414 +unsigned int DefaultLogger::GetThreadID() 1.415 +{ 1.416 + // fixme: we can get this value via boost::threads 1.417 +#ifdef WIN32 1.418 + return (unsigned int)::GetCurrentThreadId(); 1.419 +#else 1.420 + return 0; // not supported 1.421 +#endif 1.422 +} 1.423 + 1.424 +// ---------------------------------------------------------------------------------- 1.425 + 1.426 +} // !namespace Assimp