mirror of
https://github.com/mcneel/opennurbs.git
synced 2026-03-01 11:36:09 +08:00
712 lines
16 KiB
C++
712 lines
16 KiB
C++
//
|
|
// Copyright (c) 1993-2022 Robert McNeel & Associates. All rights reserved.
|
|
// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert
|
|
// McNeel & Associates.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
|
|
// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
|
|
// MERCHANTABILITY ARE HEREBY DISCLAIMED.
|
|
//
|
|
// For complete openNURBS copyright information see <http://www.opennurbs.org>.
|
|
//
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
#include "opennurbs.h"
|
|
|
|
#if !defined(ON_COMPILING_OPENNURBS)
|
|
// This check is included in all opennurbs source .c and .cpp files to insure
|
|
// ON_COMPILING_OPENNURBS is defined when opennurbs source is compiled.
|
|
// When opennurbs source is being compiled, ON_COMPILING_OPENNURBS is defined
|
|
// and the opennurbs .h files alter what is declared and how it is declared.
|
|
#error ON_COMPILING_OPENNURBS must be defined when compiling opennurbs
|
|
#endif
|
|
|
|
|
|
// openNURBS Geometry Library Errors and Warnings
|
|
//
|
|
// If an error condition occurs during a openNURBS Geometry Library
|
|
// computation, the ON_Error() function is called, the computation is
|
|
// stopped, and an error code (negative integer ) is returned. If a
|
|
// warning condition occurs during a Trout Lake Geometry Library
|
|
// computation, the ON_Warning() function is called and the computation
|
|
// continues.
|
|
//
|
|
// ON_GetErrorCount()
|
|
// ON_GetWarningCount()
|
|
// ON_Error()
|
|
// ON_Warning()
|
|
//
|
|
|
|
#define ON_MAX_ERROR_MESSAGE_COUNT ((int)ON_ErrorLog::MaximumEventCount)
|
|
|
|
static int ON_ERROR_COUNT = 0;
|
|
static int ON_WARNING_COUNT = 0;
|
|
static int ON_MATH_ERROR_COUNT = 0;
|
|
class ON_ErrorLog* ON_ACTIVE_ERROR_LOG = nullptr;
|
|
|
|
|
|
|
|
static int ON_DEBUG_ERROR_MESSAGE_OPTION = 0;
|
|
|
|
|
|
int ON_GetErrorCount(void)
|
|
{
|
|
return ON_ERROR_COUNT;
|
|
}
|
|
|
|
int ON_GetWarningCount(void)
|
|
{
|
|
return ON_WARNING_COUNT;
|
|
}
|
|
|
|
int ON_GetMathErrorCount(void)
|
|
{
|
|
return ON_MATH_ERROR_COUNT;
|
|
}
|
|
|
|
|
|
int ON_GetDebugErrorMessage(void)
|
|
{
|
|
return ON_DEBUG_ERROR_MESSAGE_OPTION?true:false;
|
|
}
|
|
|
|
|
|
void ON_EnableDebugErrorMessage( int bEnableDebugErrorMessage )
|
|
{
|
|
ON_DEBUG_ERROR_MESSAGE_OPTION = bEnableDebugErrorMessage ? 1 : 0;
|
|
}
|
|
|
|
|
|
void ON_MathError(
|
|
const char* sModuleName,
|
|
const char* sErrorType,
|
|
const char* sFunctionName
|
|
)
|
|
{
|
|
ON_MATH_ERROR_COUNT++;
|
|
|
|
if ( 0 == sModuleName)
|
|
sModuleName = "";
|
|
if ( 0 == sErrorType )
|
|
sErrorType = "";
|
|
if ( 0 == sFunctionName )
|
|
sFunctionName = "";
|
|
|
|
if ( 0 != sModuleName[0] || 0 != sErrorType[0] || 0 != sFunctionName[0] )
|
|
{
|
|
ON_ErrorEx(__FILE__,__LINE__,sFunctionName,
|
|
"Math library or floating point ERROR # %d module=%s type=%s function=%s",
|
|
ON_MATH_ERROR_COUNT,
|
|
sModuleName, // rhino.exe, opennurbs.dll, etc.
|
|
sErrorType,
|
|
sFunctionName
|
|
);
|
|
}
|
|
else
|
|
{
|
|
ON_ErrorEx(__FILE__,__LINE__,sFunctionName,
|
|
"Math library or floating point ERROR # %d",
|
|
ON_MATH_ERROR_COUNT
|
|
);
|
|
}
|
|
}
|
|
|
|
static void ON_IncrementErrorCount()
|
|
{
|
|
ON_ERROR_COUNT++;
|
|
}
|
|
|
|
static void ON_IncrementWarningCount()
|
|
{
|
|
ON_WARNING_COUNT++;
|
|
}
|
|
|
|
void ON_BrepIncrementErrorCount()
|
|
{
|
|
ON_ERROR_COUNT++;
|
|
ON_Brep::ErrorCount++;
|
|
}
|
|
|
|
void ON_SubDIncrementErrorCount()
|
|
{
|
|
ON_ERROR_COUNT++;
|
|
ON_SubD::ErrorCount++;
|
|
}
|
|
|
|
|
|
bool ON_IsNotValid()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
static bool ON_Internal_PrintErrorMessage()
|
|
{
|
|
return (0 != ON_DEBUG_ERROR_MESSAGE_OPTION && ON_ERROR_COUNT <= ON_MAX_ERROR_MESSAGE_COUNT);
|
|
}
|
|
|
|
static bool ON_Internal_PrintWarningMessage()
|
|
{
|
|
return (0 != ON_DEBUG_ERROR_MESSAGE_OPTION && ON_WARNING_COUNT <= ON_MAX_ERROR_MESSAGE_COUNT);
|
|
}
|
|
|
|
|
|
static bool ON_Internal_LogError()
|
|
{
|
|
return (nullptr != ON_ACTIVE_ERROR_LOG);
|
|
}
|
|
|
|
static void ON_Internal_RecordErrorEvent(
|
|
const ON_ErrorEvent& error_event,
|
|
bool bPrint
|
|
)
|
|
{
|
|
if (nullptr != ON_ACTIVE_ERROR_LOG)
|
|
ON_ACTIVE_ERROR_LOG->Append(error_event);
|
|
|
|
|
|
if ( 0 == ON_DEBUG_ERROR_MESSAGE_OPTION )
|
|
return;
|
|
|
|
if (false == bPrint)
|
|
return;
|
|
|
|
|
|
const ON_ErrorEvent::Type error_type = error_event.EventType();
|
|
ON_String s;
|
|
if ( ON_ErrorEvent::Type::Warning == error_type )
|
|
{
|
|
if (ON_WARNING_COUNT == ON_MAX_ERROR_MESSAGE_COUNT)
|
|
s = ON_String::FormatToString("ON_WARNING # %d: ... suspending warning messages.", ON_WARNING_COUNT);
|
|
else
|
|
s = ON_String::FormatToString("ON_WARNING # %d: ", ON_WARNING_COUNT) + error_event.ToString();
|
|
}
|
|
else
|
|
{
|
|
if (ON_ERROR_COUNT == ON_MAX_ERROR_MESSAGE_COUNT)
|
|
s = ON_String::FormatToString("ON_ERROR # %d: ... suspending error messages.", ON_ERROR_COUNT);
|
|
else
|
|
s = ON_String::FormatToString("ON_ERROR # %d: ", ON_ERROR_COUNT) + error_event.ToString();
|
|
}
|
|
|
|
if ( s.IsNotEmpty() )
|
|
{
|
|
int obsolete_type;
|
|
switch (error_type)
|
|
{
|
|
case ON_ErrorEvent::Type::Unset:
|
|
obsolete_type = 0;
|
|
break;
|
|
case ON_ErrorEvent::Type::Warning:
|
|
obsolete_type = 0;
|
|
break;
|
|
case ON_ErrorEvent::Type::Error:
|
|
obsolete_type = 1;
|
|
break;
|
|
case ON_ErrorEvent::Type::Assert:
|
|
obsolete_type = 2;
|
|
break;
|
|
case ON_ErrorEvent::Type::Custom:
|
|
obsolete_type = 0;
|
|
break;
|
|
case ON_ErrorEvent::Type::SubDError:
|
|
obsolete_type = 0;
|
|
break;
|
|
case ON_ErrorEvent::Type::NotValid:
|
|
obsolete_type = 0;
|
|
break;
|
|
default:
|
|
obsolete_type = 0;
|
|
break;
|
|
}
|
|
ON_ErrorMessage(obsolete_type,static_cast<const char*>(s));
|
|
}
|
|
}
|
|
|
|
void ON_VARGS_FUNC_CDECL ON_Error(
|
|
const char* sFileName,
|
|
int line_number,
|
|
const char* sFormat,
|
|
...
|
|
)
|
|
{
|
|
ON_IncrementErrorCount();
|
|
|
|
const bool bPrintErrorMessage = ON_Internal_PrintErrorMessage();
|
|
if ( bPrintErrorMessage || ON_Internal_LogError() )
|
|
{
|
|
ON_String description;
|
|
if (sFormat && sFormat[0])
|
|
{
|
|
va_list args;
|
|
va_start(args, sFormat);
|
|
description.FormatVargs(sFormat, args);
|
|
va_end(args);
|
|
}
|
|
|
|
const ON_ErrorEvent error_event(
|
|
ON_ErrorEvent::Type::Error,
|
|
sFileName,
|
|
(unsigned int)line_number,
|
|
nullptr,
|
|
description
|
|
);
|
|
|
|
ON_Internal_RecordErrorEvent(error_event, bPrintErrorMessage);
|
|
}
|
|
|
|
}
|
|
|
|
void ON_VARGS_FUNC_CDECL ON_ErrorEx(
|
|
const char* sFileName,
|
|
int line_number,
|
|
const char* sFunctionName,
|
|
const char* sFormat,
|
|
...
|
|
)
|
|
{
|
|
ON_IncrementErrorCount();
|
|
|
|
const bool bPrintErrorMessage = ON_Internal_PrintErrorMessage();
|
|
if (bPrintErrorMessage || ON_Internal_LogError())
|
|
{
|
|
ON_String description;
|
|
if (sFormat && sFormat[0])
|
|
{
|
|
va_list args;
|
|
va_start(args, sFormat);
|
|
description.FormatVargs(sFormat, args);
|
|
va_end(args);
|
|
}
|
|
|
|
const ON_ErrorEvent error_event(
|
|
ON_ErrorEvent::Type::Error,
|
|
sFileName,
|
|
(unsigned int)line_number,
|
|
sFunctionName,
|
|
description
|
|
);
|
|
|
|
ON_Internal_RecordErrorEvent(error_event, bPrintErrorMessage);
|
|
}
|
|
|
|
}
|
|
|
|
void ON_VARGS_FUNC_CDECL ON_Warning(
|
|
const char* sFileName,
|
|
int line_number,
|
|
const char* sFormat,
|
|
...
|
|
)
|
|
{
|
|
ON_IncrementWarningCount();
|
|
|
|
const bool bPrintErrorMessage = ON_Internal_PrintWarningMessage();
|
|
if ( bPrintErrorMessage || ON_Internal_LogError())
|
|
{
|
|
ON_String description;
|
|
if (sFormat && sFormat[0])
|
|
{
|
|
va_list args;
|
|
va_start(args, sFormat);
|
|
description.FormatVargs(sFormat, args);
|
|
va_end(args);
|
|
}
|
|
|
|
const ON_ErrorEvent error_event(
|
|
ON_ErrorEvent::Type::Warning,
|
|
sFileName,
|
|
(unsigned int)line_number,
|
|
nullptr,
|
|
description
|
|
);
|
|
|
|
ON_Internal_RecordErrorEvent(error_event, bPrintErrorMessage);
|
|
}
|
|
|
|
}
|
|
|
|
void ON_VARGS_FUNC_CDECL ON_WarningEx(
|
|
const char* sFileName,
|
|
int line_number,
|
|
const char* sFunctionName,
|
|
const char* sFormat,
|
|
...
|
|
)
|
|
{
|
|
ON_IncrementWarningCount();
|
|
|
|
const bool bPrintErrorMessage = ON_Internal_PrintWarningMessage();
|
|
if ( bPrintErrorMessage || ON_Internal_LogError())
|
|
{
|
|
ON_String description;
|
|
if (sFormat && sFormat[0])
|
|
{
|
|
va_list args;
|
|
va_start(args, sFormat);
|
|
description.FormatVargs(sFormat, args);
|
|
va_end(args);
|
|
}
|
|
|
|
const ON_ErrorEvent error_event(
|
|
ON_ErrorEvent::Type::Warning,
|
|
sFileName,
|
|
(unsigned int)line_number,
|
|
sFunctionName,
|
|
description
|
|
);
|
|
|
|
ON_Internal_RecordErrorEvent(error_event, bPrintErrorMessage);
|
|
}
|
|
|
|
}
|
|
|
|
void ON_VARGS_FUNC_CDECL ON_REMOVE_ASAP_AssertEx(
|
|
int bCondition,
|
|
const char* sFileName,
|
|
int line_number,
|
|
const char* sFunctionName,
|
|
const char* sFormat,
|
|
...
|
|
)
|
|
{
|
|
if ( false == bCondition)
|
|
{
|
|
|
|
const bool bPrintErrorMessage = ON_Internal_PrintErrorMessage();
|
|
if ( bPrintErrorMessage || ON_Internal_LogError())
|
|
{
|
|
ON_String description;
|
|
if (sFormat && sFormat[0])
|
|
{
|
|
va_list args;
|
|
va_start(args, sFormat);
|
|
description.FormatVargs(sFormat, args);
|
|
va_end(args);
|
|
}
|
|
|
|
const ON_ErrorEvent error_event(
|
|
ON_ErrorEvent::Type::Warning,
|
|
sFileName,
|
|
(unsigned int)line_number,
|
|
sFunctionName,
|
|
description
|
|
);
|
|
|
|
ON_Internal_RecordErrorEvent(error_event, bPrintErrorMessage);
|
|
}
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// ON_ErrorEvent
|
|
//
|
|
ON_ErrorEvent::ON_ErrorEvent(const ON_ErrorEvent& src)
|
|
{
|
|
Internal_CopyFrom(src);
|
|
}
|
|
|
|
ON_ErrorEvent& ON_ErrorEvent::operator=(const ON_ErrorEvent& src)
|
|
{
|
|
if (this != &src)
|
|
{
|
|
Internal_CopyFrom(src);
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
void ON_ErrorEvent::Internal_CopyFrom(const ON_ErrorEvent& src)
|
|
{
|
|
m_event_type = src.m_event_type;
|
|
m_line_number = src.m_line_number;
|
|
m_file_name = nullptr;
|
|
m_function_name = nullptr;
|
|
m_description = nullptr;
|
|
|
|
const size_t sizeof_buffer = sizeof(m_buffer);
|
|
memcpy(m_buffer, src.m_buffer, sizeof_buffer);
|
|
|
|
// buffer_capacity keeps code working if char changes to wchar_t
|
|
const size_t buffer_capacity = sizeof_buffer/sizeof(m_buffer[0]);
|
|
const char* src_buffer = &src.m_buffer[0];
|
|
|
|
if (nullptr != src.m_file_name && src.m_file_name >= src_buffer)
|
|
{
|
|
const size_t i = (src.m_file_name - src_buffer);
|
|
if (i >= 0 && i < buffer_capacity)
|
|
m_file_name = &m_buffer[i];
|
|
}
|
|
if (nullptr != src.m_function_name && src.m_function_name >= src_buffer)
|
|
{
|
|
const size_t i = (src.m_function_name - src_buffer);
|
|
if (i >= 0 && i < buffer_capacity)
|
|
m_function_name = &m_buffer[i];
|
|
}
|
|
if (nullptr != src.m_description && src.m_description >= src_buffer)
|
|
{
|
|
const size_t i = (src.m_description - src_buffer);
|
|
if (i >= 0 && i < buffer_capacity)
|
|
m_description = &m_buffer[i];
|
|
}
|
|
}
|
|
|
|
|
|
ON_ErrorEvent::ON_ErrorEvent(
|
|
ON_ErrorEvent::Type event_type,
|
|
const char* file_name,
|
|
unsigned int line_number,
|
|
const char* function_name,
|
|
const char* description
|
|
)
|
|
: m_event_type(event_type)
|
|
, m_line_number(line_number)
|
|
{
|
|
const size_t buffer_capacity = sizeof(m_buffer) / sizeof(m_buffer[0]);
|
|
size_t file_name_length = ON_String::Length(file_name);
|
|
size_t function_name_length = ON_String::Length(function_name);
|
|
size_t description_length = ON_String::Length(description);
|
|
if (file_name_length + function_name_length + description_length + 3 > buffer_capacity)
|
|
{
|
|
const size_t cap = buffer_capacity / 4;
|
|
if (file_name_length > cap )
|
|
{
|
|
file_name += (file_name_length - cap);
|
|
file_name_length = cap;
|
|
}
|
|
if (file_name_length + function_name_length + description_length + 3 > buffer_capacity)
|
|
{
|
|
if (function_name_length > cap)
|
|
{
|
|
function_name += (function_name_length - cap);
|
|
function_name_length = cap;
|
|
}
|
|
}
|
|
}
|
|
|
|
char* c = m_buffer;
|
|
char* c1 = m_buffer + (buffer_capacity - 1);
|
|
|
|
if (file_name_length > 0 && c < c1)
|
|
{
|
|
m_file_name = c;
|
|
for (size_t i = 0; i < file_name_length && c < c1; i++)
|
|
*c++ = file_name[i];
|
|
if (c < c1)
|
|
*c++ = 0;
|
|
}
|
|
|
|
if (function_name_length > 0 && c < c1)
|
|
{
|
|
m_function_name = c;
|
|
for (size_t i = 0; i < function_name_length && c < c1; i++)
|
|
*c++ = function_name[i];
|
|
if (c < c1)
|
|
*c++ = 0;
|
|
}
|
|
|
|
if (description_length > 0 && c < c1)
|
|
{
|
|
m_description = c;
|
|
for (size_t i = 0; i < description_length && c < c1; i++)
|
|
*c++ = description[i];
|
|
if (c < c1)
|
|
*c++ = 0;
|
|
}
|
|
|
|
*c1 = 0;
|
|
}
|
|
|
|
const ON_ErrorEvent ON_ErrorEvent::Create(
|
|
ON_ErrorEvent::Type event_type,
|
|
const char* file_name,
|
|
unsigned int line_number,
|
|
const char* function_name,
|
|
const char* description
|
|
)
|
|
{
|
|
return ON_ErrorEvent(
|
|
event_type,
|
|
file_name,
|
|
line_number,
|
|
function_name,
|
|
description
|
|
);
|
|
}
|
|
|
|
const char* ON_ErrorEvent::FileName() const
|
|
{
|
|
return (nullptr != m_file_name || 0 != m_file_name) ? m_file_name : "";
|
|
}
|
|
|
|
const char* ON_ErrorEvent::FunctionName() const
|
|
{
|
|
return (nullptr != m_function_name || 0 != m_function_name) ? m_function_name : "";
|
|
}
|
|
|
|
const char* ON_ErrorEvent::Description() const
|
|
{
|
|
return (nullptr != m_description || 0 != m_description) ? m_description : "";
|
|
}
|
|
|
|
unsigned int ON_ErrorEvent::LineNumber() const
|
|
{
|
|
return m_line_number;
|
|
}
|
|
|
|
ON_ErrorEvent::Type ON_ErrorEvent::EventType() const
|
|
{
|
|
return m_event_type;
|
|
}
|
|
|
|
const char* ON_ErrorEvent::TypeToString(
|
|
ON_ErrorEvent::Type event_type
|
|
)
|
|
{
|
|
const char* s;
|
|
switch (event_type)
|
|
{
|
|
case ON_ErrorEvent::Type::Unset:
|
|
s = "Unset";
|
|
break;
|
|
case ON_ErrorEvent::Type::Warning:
|
|
s = "Warning";
|
|
break;
|
|
case ON_ErrorEvent::Type::Error:
|
|
s = "Error";
|
|
break;
|
|
case ON_ErrorEvent::Type::Assert:
|
|
s = "Assert";
|
|
break;
|
|
case ON_ErrorEvent::Type::Custom:
|
|
s = "Custom";
|
|
break;
|
|
case ON_ErrorEvent::Type::SubDError:
|
|
s = "SubDError";
|
|
break;
|
|
case ON_ErrorEvent::Type::NotValid:
|
|
s = "NotValid";
|
|
break;
|
|
default:
|
|
s = "Invalid";
|
|
break;
|
|
}
|
|
|
|
return s;
|
|
}
|
|
|
|
const ON_String ON_ErrorEvent::ToString() const
|
|
{
|
|
const char* function_name = FunctionName();
|
|
const char* description = Description();
|
|
if (0 != function_name[0])
|
|
{
|
|
return ON_String::FormatToString(
|
|
"%s.%u %s(): %s \"%s\"",
|
|
FileName(),
|
|
LineNumber(),
|
|
function_name,
|
|
ON_ErrorEvent::TypeToString(m_event_type),
|
|
description
|
|
);
|
|
}
|
|
return ON_String::FormatToString(
|
|
"%s.%u: %s \"%s\"",
|
|
FileName(),
|
|
LineNumber(),
|
|
ON_ErrorEvent::TypeToString(m_event_type),
|
|
description
|
|
);
|
|
}
|
|
|
|
void ON_ErrorEvent::Dump(
|
|
class ON_TextLog& text_log
|
|
) const
|
|
{
|
|
const ON_String s(ToString());
|
|
text_log.Print("%s\n", static_cast<const char*>(s));
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// ON_ErrorLog
|
|
//
|
|
|
|
bool ON_ErrorLog::EnableLogging()
|
|
{
|
|
if ( 0 == ((ON__UINT_PTR)this) )
|
|
return false;
|
|
if (this == ON_ACTIVE_ERROR_LOG)
|
|
return true;
|
|
if (nullptr != ON_ACTIVE_ERROR_LOG)
|
|
return false;
|
|
if (Count() >= ON_ErrorLog::MaximumEventCount)
|
|
return false;
|
|
|
|
ON_ACTIVE_ERROR_LOG = this;
|
|
return true;
|
|
}
|
|
|
|
void ON_ErrorLog::DisableLogging()
|
|
{
|
|
if (nullptr != ON_ACTIVE_ERROR_LOG && this == ON_ACTIVE_ERROR_LOG)
|
|
{
|
|
ON_ACTIVE_ERROR_LOG = nullptr;
|
|
}
|
|
}
|
|
|
|
void ON_ErrorLog::Dump(
|
|
class ON_TextLog& text_log
|
|
) const
|
|
{
|
|
const unsigned int count = Count();
|
|
text_log.Print("Error log: %u events\n", count);
|
|
ON_TextLogIndent indent1(text_log);
|
|
for (unsigned int i = 0; i < count; i++)
|
|
{
|
|
m_events[i].Dump(text_log);
|
|
}
|
|
}
|
|
|
|
|
|
ON_ErrorLog::~ON_ErrorLog()
|
|
{
|
|
if (ON_ACTIVE_ERROR_LOG == this)
|
|
ON_ACTIVE_ERROR_LOG = nullptr;
|
|
}
|
|
|
|
unsigned int ON_ErrorLog::Append(
|
|
const ON_ErrorEvent& error_event
|
|
)
|
|
{
|
|
const unsigned int event_capacity = (unsigned int)(sizeof(m_events) / sizeof(m_events[0]));
|
|
if (m_event_count >= event_capacity)
|
|
return 0;
|
|
|
|
if (m_event_count < event_capacity)
|
|
{
|
|
m_events[m_event_count++] = error_event;
|
|
if (m_event_count == event_capacity && ON_ACTIVE_ERROR_LOG == this)
|
|
{
|
|
// stop wasting time logging errors
|
|
ON_ACTIVE_ERROR_LOG = nullptr;
|
|
}
|
|
}
|
|
return m_event_count;
|
|
}
|
|
|
|
unsigned int ON_ErrorLog::Count() const
|
|
{
|
|
return m_event_count <= ON_ErrorLog::MaximumEventCount ? m_event_count : ON_ErrorLog::MaximumEventCount;
|
|
}
|
|
|
|
const ON_ErrorEvent& ON_ErrorLog::Event(unsigned int i) const
|
|
{
|
|
return (i < m_event_count) ? m_events[i] : ON_ErrorEvent::Unset;
|
|
}
|
|
|
|
void ON_ErrorLog::Clear()
|
|
{
|
|
m_event_count = 0;
|
|
}
|