mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-10 07:26:03 -06:00
486f383de7
Pdm fields can contain a forward declared Pdm object without the include file VizFwk: Added VertexColoring shader to be able to use per vertex color used from drawableGeo::setColorArray()
490 lines
15 KiB
C++
490 lines
15 KiB
C++
//##################################################################################################
|
|
//
|
|
// Custom Visualization Core library
|
|
// Copyright (C) 2011-2013 Ceetron AS
|
|
//
|
|
// This library may be used under the terms of either the GNU General Public License or
|
|
// the GNU Lesser General Public License as follows:
|
|
//
|
|
// GNU General Public License Usage
|
|
// This library is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
// FITNESS FOR A PARTICULAR PURPOSE.
|
|
//
|
|
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
|
// for more details.
|
|
//
|
|
// GNU Lesser General Public License Usage
|
|
// This library is free software; you can redistribute it and/or modify
|
|
// it under the terms of the GNU Lesser General Public License as published by
|
|
// the Free Software Foundation; either version 2.1 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
// FITNESS FOR A PARTICULAR PURPOSE.
|
|
//
|
|
// See the GNU Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
|
|
// for more details.
|
|
//
|
|
//##################################################################################################
|
|
|
|
|
|
#include "cvfBase.h"
|
|
#include "cvfAssert.h"
|
|
#include "cvfSystem.h"
|
|
|
|
#include <cstdlib>
|
|
#include <iostream>
|
|
#include <string>
|
|
|
|
#ifdef WIN32
|
|
#pragma warning (push)
|
|
#pragma warning (disable: 4668)
|
|
#include <windows.h>
|
|
#pragma warning (pop)
|
|
#include <io.h>
|
|
#include <signal.h>
|
|
#include <fcntl.h>
|
|
#endif
|
|
|
|
namespace cvf {
|
|
|
|
|
|
// User actions (interactive responses)
|
|
static const int USERACTION_CONTINUE = 0;
|
|
static const int USERACTION_DEBUGBREAK = 1;
|
|
static const int USERACTION_ABORT = 2;
|
|
|
|
|
|
|
|
//==================================================================================================
|
|
///
|
|
/// \class cvf::AssertHandler
|
|
/// \ingroup Core
|
|
///
|
|
/// Base class for assert handlers
|
|
///
|
|
//==================================================================================================
|
|
class AssertHandler
|
|
{
|
|
public:
|
|
virtual ~AssertHandler() {}
|
|
virtual Assert::FailAction handleAssert(const char* fileName, int lineNumber, const char* expr, const char* msg) = 0;
|
|
};
|
|
|
|
|
|
|
|
//==================================================================================================
|
|
///
|
|
/// \class cvf::AssertHandlerConsole
|
|
/// \ingroup Core
|
|
///
|
|
/// Assert handler for basic assert output to console
|
|
///
|
|
//==================================================================================================
|
|
class AssertHandlerConsole : public AssertHandler
|
|
{
|
|
public:
|
|
virtual Assert::FailAction handleAssert(const char* fileName, int lineNumber, const char* expr, const char* msg);
|
|
|
|
private:
|
|
static void reportToConsole(const char* fileName, int lineNumber, const char* expr, const char* msg);
|
|
static int askForUserActionUsingConsole();
|
|
#ifdef WIN32
|
|
static void winCreateConsoleAndRedirectIO(bool redirectInput);
|
|
#endif
|
|
};
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Show report of a failed assert in console and abort execution
|
|
///
|
|
/// On Windows, a console will be created if one doesn't exist (GUI applications)
|
|
//--------------------------------------------------------------------------------------------------
|
|
Assert::FailAction AssertHandlerConsole::handleAssert(const char* fileName, int lineNumber, const char* expr, const char* msg)
|
|
{
|
|
// Just shows assert message in console.
|
|
// Does the job on both Windows and Linux (creates a console on Windows if one doesn't exist)
|
|
reportToConsole(fileName, lineNumber, expr, msg);
|
|
|
|
#ifdef _MSC_VER
|
|
#if (_MSC_VER >= 1600)
|
|
if (::IsDebuggerPresent())
|
|
#endif
|
|
{
|
|
__debugbreak();
|
|
}
|
|
#endif
|
|
|
|
abort();
|
|
|
|
// Shouldn't really matter since we always abort
|
|
return Assert::CONTINUE;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void AssertHandlerConsole::reportToConsole(const char* fileName, int lineNumber, const char* expr, const char* msg)
|
|
{
|
|
#ifdef WIN32
|
|
// Make sure we have a console (applicable to Windows GUI applications)
|
|
winCreateConsoleAndRedirectIO(false);
|
|
#endif
|
|
|
|
std::cerr << "Assertion failed:";
|
|
|
|
if (expr)
|
|
{
|
|
std::cerr << " (" << expr << ")";
|
|
}
|
|
|
|
if (msg)
|
|
{
|
|
std::cerr << " '" << msg << "'";
|
|
}
|
|
|
|
if (expr || msg)
|
|
{
|
|
std::cerr << ",";
|
|
}
|
|
|
|
std::cerr << " file " << fileName << ", line " << lineNumber << std::endl;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Ask for user action using console input
|
|
///
|
|
/// \return One of the USERACTION_ constants
|
|
//--------------------------------------------------------------------------------------------------
|
|
int AssertHandlerConsole::askForUserActionUsingConsole()
|
|
{
|
|
#ifdef WIN32
|
|
// Make sure we have a console (applicable to Windows GUI applications)
|
|
// Also ensures that input is redirected
|
|
winCreateConsoleAndRedirectIO(true);
|
|
#endif
|
|
|
|
// Let abort be the default choice
|
|
#ifdef WIN32
|
|
std::cerr << "Choose action: [A]bort, [R]etry (debug) or [I]gnore: default [A]\n";
|
|
#else
|
|
std::cerr << "Choose action: [A]bort or [I]gnore: default [A]\n";
|
|
#endif
|
|
|
|
// Reset failstate, just in case.
|
|
std::cin.clear();
|
|
|
|
std::string line;
|
|
while (std::getline(std::cin, line))
|
|
{
|
|
int ch = 0;
|
|
if (!std::cin.fail() && line.length() == 1)
|
|
{
|
|
ch = tolower(line[0]);
|
|
}
|
|
|
|
if (ch == 'i')
|
|
{
|
|
return USERACTION_CONTINUE;
|
|
}
|
|
#ifdef WIN32
|
|
else if (ch == 'r')
|
|
{
|
|
return USERACTION_DEBUGBREAK;
|
|
}
|
|
#endif
|
|
else if (ch == 'a' || line.length() == 0)
|
|
{
|
|
return USERACTION_ABORT;
|
|
}
|
|
}
|
|
|
|
return USERACTION_ABORT;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Creates a console and redirects I/O from/to it (Windows only)
|
|
///
|
|
/// \param redirectInput If true, input will also be redirected.
|
|
///
|
|
/// Function is useful for Windows GUI applications. Allocates a console if it doesn't exist and
|
|
/// then redirects output to the console. Also redirects input if \a redirectInput is true
|
|
//--------------------------------------------------------------------------------------------------
|
|
#ifdef WIN32
|
|
void AssertHandlerConsole::winCreateConsoleAndRedirectIO(bool redirectInput)
|
|
{
|
|
// Allocate a new console for this app
|
|
// Only one console can be associated with an app, so should fail if a console is already present.
|
|
AllocConsole();
|
|
|
|
|
|
bool redirStdOut = true;
|
|
bool redirStdErr = true;
|
|
bool redirStdIn = redirectInput;
|
|
|
|
if (redirStdOut)
|
|
{
|
|
HANDLE stdHandle = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT);
|
|
FILE* fp = _fdopen(fileDescriptor, "w");
|
|
|
|
*stdout = *fp;
|
|
setvbuf(stdout, NULL, _IONBF, 0);
|
|
}
|
|
|
|
if (redirStdErr)
|
|
{
|
|
HANDLE stdHandle = GetStdHandle(STD_ERROR_HANDLE);
|
|
int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT);
|
|
FILE* fp = _fdopen(fileDescriptor, "w");
|
|
|
|
*stderr = *fp;
|
|
setvbuf(stderr, NULL, _IONBF, 0);
|
|
}
|
|
|
|
if (redirStdIn)
|
|
{
|
|
HANDLE stdHandle = GetStdHandle(STD_INPUT_HANDLE);
|
|
int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT);
|
|
FILE* fp = _fdopen(fileDescriptor, "r");
|
|
|
|
*stdin = *fp;
|
|
setvbuf(stdin, NULL, _IONBF, 0);
|
|
}
|
|
|
|
|
|
// Make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog point to console as well
|
|
std::ios::sync_with_stdio();
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
//==================================================================================================
|
|
///
|
|
/// \class cvf::AssertHandlerWinDialog
|
|
/// \ingroup Core
|
|
///
|
|
/// Assert handler for Windows, using a dialog with interaction
|
|
///
|
|
//==================================================================================================
|
|
#ifdef WIN32
|
|
class AssertHandlerWinDialog : public AssertHandler
|
|
{
|
|
public:
|
|
virtual Assert::FailAction handleAssert(const char* fileName, int lineNumber, const char* expr, const char* msg);
|
|
|
|
private:
|
|
static int handleUsingDialog(const char* fileName, int lineNumber, const char* expr, const char* msg);
|
|
#ifdef _DEBUG
|
|
static int handleUsingCrtDbgReport(const char* fileName, int lineNumber, const char* expr, const char* msg);
|
|
#endif
|
|
};
|
|
#endif
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
#ifdef WIN32
|
|
Assert::FailAction AssertHandlerWinDialog::handleAssert(const char* fileName, int lineNumber, const char* expr, const char* msg)
|
|
{
|
|
//int retVal = handleUsingCrtDbgReport(fileName, lineNumber, expr, msg);
|
|
int retVal = handleUsingDialog(fileName, lineNumber, expr, msg);
|
|
|
|
if (retVal == USERACTION_CONTINUE)
|
|
{
|
|
return Assert::CONTINUE;
|
|
}
|
|
else if (retVal == USERACTION_DEBUGBREAK)
|
|
{
|
|
return Assert::DEBUGBREAK;
|
|
}
|
|
else if (retVal == USERACTION_ABORT)
|
|
{
|
|
// From __crtMessageWindow() in response to user clicking abort button
|
|
// Note that it is better NOT to call abort() here, because the default implementation of abort() will call Watson
|
|
// raise abort signal
|
|
raise(SIGABRT);
|
|
|
|
// We usually won't get here, but it's possible that SIGABRT was ignored.
|
|
// So exit the program anyway.
|
|
_exit(3);
|
|
}
|
|
|
|
// Shouldn't be getting here
|
|
abort();
|
|
return Assert::CONTINUE;
|
|
}
|
|
#endif
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Shows message in interactive dialog and lets user choose how to proceed
|
|
///
|
|
/// \return Returns one of the USERACTION_ constants depending on which button the user chooses.
|
|
///
|
|
/// Compared to the handleUsingCrtDbgReport() function, this function will also work in release builds
|
|
/// As opposed to the handleUsingCrtDbgReport(), this function will not call abort, but will return
|
|
/// USERACTION_ABORT instead.
|
|
///
|
|
/// \todo Must add code to handle case where new assert is triggered while handling an assert
|
|
//--------------------------------------------------------------------------------------------------
|
|
#ifdef WIN32
|
|
int AssertHandlerWinDialog::handleUsingDialog(const char* fileName, int lineNumber, const char* expr, const char* msg)
|
|
{
|
|
char szMsgBuf[2048];
|
|
|
|
System::strcpy(szMsgBuf, sizeof(szMsgBuf), "Assertion failed\n");
|
|
|
|
System::strcat(szMsgBuf, sizeof(szMsgBuf), "\nFile: ");
|
|
if (fileName)
|
|
{
|
|
System::strcat(szMsgBuf, sizeof(szMsgBuf), fileName);
|
|
}
|
|
|
|
System::strcat(szMsgBuf, sizeof(szMsgBuf), "\nLine: ");
|
|
if (lineNumber >= 0)
|
|
{
|
|
char szLinNumBuf[20];
|
|
System::sprintf(szLinNumBuf, sizeof(szLinNumBuf), "%d", lineNumber);
|
|
System::strcat(szMsgBuf, sizeof(szMsgBuf), szLinNumBuf);
|
|
}
|
|
|
|
|
|
if (expr)
|
|
{
|
|
System::strcat(szMsgBuf, sizeof(szMsgBuf), "\n\n");
|
|
System::strcat(szMsgBuf, sizeof(szMsgBuf), "Expression: ");
|
|
System::strcat(szMsgBuf, sizeof(szMsgBuf), expr);
|
|
}
|
|
|
|
if (msg)
|
|
{
|
|
System::strcat(szMsgBuf, sizeof(szMsgBuf), "\n\n");
|
|
System::strcat(szMsgBuf, sizeof(szMsgBuf), msg);
|
|
}
|
|
|
|
System::strcat(szMsgBuf, sizeof(szMsgBuf), "\n\n(Press Retry to debug application)");
|
|
|
|
|
|
int retVal = ::MessageBoxA(NULL, szMsgBuf, "Assertion Failed", MB_TASKMODAL|MB_ICONHAND|MB_ABORTRETRYIGNORE|MB_SETFOREGROUND);
|
|
|
|
if (retVal == IDIGNORE) return USERACTION_CONTINUE;
|
|
else if (retVal == IDRETRY) return USERACTION_DEBUGBREAK;
|
|
else return USERACTION_ABORT;
|
|
}
|
|
#endif
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Wrapper function for the CRT _CrtDbgReport() function
|
|
///
|
|
/// This function never returns if the user chooses 'Abort'
|
|
/// Note that the underlying function is only available in debug builds
|
|
//--------------------------------------------------------------------------------------------------
|
|
#if defined WIN32 && defined _DEBUG
|
|
int AssertHandlerWinDialog::handleUsingCrtDbgReport(const char* fileName, int lineNumber, const char* expr, const char* msg)
|
|
{
|
|
// Create message combining expression and message
|
|
char szMsgBuf[2048];
|
|
szMsgBuf[0] = '\0';
|
|
|
|
if (expr)
|
|
{
|
|
System::strcat(szMsgBuf, sizeof(szMsgBuf), expr);
|
|
}
|
|
|
|
if (msg)
|
|
{
|
|
System::strcat(szMsgBuf, sizeof(szMsgBuf), "\n");
|
|
System::strcat(szMsgBuf, sizeof(szMsgBuf), msg);
|
|
}
|
|
|
|
int retVal = _CrtDbgReport(_CRT_ASSERT, fileName, lineNumber, NULL, szMsgBuf);
|
|
|
|
if (retVal == 0) return USERACTION_CONTINUE;
|
|
else if (retVal == 1) return USERACTION_DEBUGBREAK;
|
|
else return USERACTION_ABORT;
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
//==================================================================================================
|
|
///
|
|
/// \class cvf::Assert
|
|
/// \ingroup Core
|
|
///
|
|
/// Helper class to customize assert
|
|
///
|
|
//==================================================================================================
|
|
|
|
#ifdef WIN32
|
|
AssertHandler* Assert::sm_handler = new AssertHandlerWinDialog;
|
|
#else
|
|
AssertHandler* Assert::sm_handler = new AssertHandlerConsole;
|
|
#endif
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void Assert::setReportMode(ReportMode reportMode)
|
|
{
|
|
#ifndef WIN32
|
|
if (reportMode == INTERACTIVE_DIALOG) return;
|
|
#endif
|
|
|
|
delete sm_handler;
|
|
sm_handler = NULL;
|
|
|
|
if (reportMode == CONSOLE)
|
|
{
|
|
sm_handler = new AssertHandlerConsole;
|
|
}
|
|
#ifdef WIN32
|
|
else if (reportMode == INTERACTIVE_DIALOG)
|
|
{
|
|
sm_handler = new AssertHandlerWinDialog;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Show report of a failed assert
|
|
///
|
|
/// If assertions are configured to be interactive, a message box will be shown on Windows and
|
|
/// the user may opt to ignore or trigger debugging.
|
|
/// On Linux, or if interactive asserts are disabled, the application will terminate.
|
|
///
|
|
/// \todo Add handling of cases where we get another assert while processing the first one AND
|
|
/// asserts from multiple threads.
|
|
//--------------------------------------------------------------------------------------------------
|
|
Assert::FailAction Assert::reportFailedAssert(const char* fileName, int lineNumber, const char* expr, const char* msg)
|
|
{
|
|
if (sm_handler)
|
|
{
|
|
return sm_handler->handleAssert(fileName, lineNumber, expr, msg);
|
|
}
|
|
else
|
|
{
|
|
abort();
|
|
return CONTINUE;
|
|
}
|
|
}
|
|
|
|
|
|
} // namespace cvf
|
|
|