Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Purpose: Implementation of the PCIDSKException class. 4 : * 5 : ****************************************************************************** 6 : * Copyright (c) 2009 7 : * PCI Geomatics, 90 Allstate Parkway, Markham, Ontario, Canada. 8 : * 9 : * SPDX-License-Identifier: MIT 10 : ****************************************************************************/ 11 : 12 : #include "pcidsk_config.h" 13 : #include "pcidsk_types.h" 14 : #include "pcidsk_buffer.h" 15 : #include "pcidsk_exception.h" 16 : #include <cstdlib> 17 : #include <cstring> 18 : #include <cstdio> 19 : #include <cstdarg> 20 : 21 : #if !defined(va_copy) && defined(__va_copy) 22 : #define va_copy __va_copy 23 : #endif 24 : 25 : using PCIDSK::PCIDSKException; 26 : 27 : /** 28 : 29 : \class PCIDSK::PCIDSKException 30 : 31 : \brief Generic SDK Exception 32 : 33 : The PCIDSKException class is used for all errors thrown by the PCIDSK 34 : library. It includes a formatted message and is derived from std::exception. 35 : The PCIDSK library throws all exceptions as pointers, and library exceptions 36 : should be caught like this: 37 : 38 : @code 39 : try 40 : { 41 : PCIDSKFile *file = PCIDSK::Open( "irvine.pix, "r", NULL ); 42 : } 43 : catch( PCIDSK::PCIDSKException &ex ) 44 : { 45 : fprintf( stderr, "PCIDSKException:\n%s\n", ex.what() ); 46 : exit( 1 ); 47 : } 48 : @endcode 49 : 50 : */ 51 : 52 : /************************************************************************/ 53 : /* PCIDSKException() */ 54 : /************************************************************************/ 55 : 56 : #if defined(__clang__) && __clang_major__ == 3 && __clang_minor__ <= 2 57 : #pragma clang diagnostic push 58 : #pragma clang diagnostic ignored "-Wunknown-pragmas" 59 : #pragma clang diagnostic ignored "-Wdocumentation" 60 : #endif 61 : 62 : 63 : /** 64 : * Create exception with formatted message. 65 : * 66 : * This constructor supports formatting of an exception message 67 : * using printf style format and additional arguments. 68 : * 69 : * @param fmt the printf style format (eg. "Illegal value:%d") 70 : * @param ... additional arguments as required by the format string. 71 : */ 72 : 73 0 : PCIDSKException::PCIDSKException( const char *fmt, ... ) 74 : 75 : { 76 : std::va_list args; 77 : 78 0 : va_start( args, fmt ); 79 0 : vPrintf( fmt, args ); 80 0 : va_end( args ); 81 0 : } 82 : 83 : #if defined(__clang__) && __clang_major__ == 3 && __clang_minor__ <= 2 84 : #pragma clang diagnostic pop 85 : #endif 86 : 87 : /************************************************************************/ 88 : /* ~PCIDSKException() */ 89 : /************************************************************************/ 90 : 91 : /** 92 : * Destructor. 93 : */ 94 : 95 112 : PCIDSKException::~PCIDSKException() throw() 96 : 97 : { 98 112 : } 99 : 100 : /************************************************************************/ 101 : /* vPrintf() */ 102 : /************************************************************************/ 103 : 104 : /** 105 : * Format a message. 106 : * 107 : * Assigns a message to an exception using printf style formatting 108 : * and va_list arguments (similar to vfprintf(). 109 : * 110 : * @param fmt printf style format string. 111 : * @param args additional arguments as required. 112 : */ 113 : 114 : 115 56 : void PCIDSKException::vPrintf( const char *fmt, std::va_list args ) 116 : 117 : { 118 : /* -------------------------------------------------------------------- */ 119 : /* This implementation for platforms without vsnprintf() will */ 120 : /* just plain fail if the formatted contents are too large. */ 121 : /* -------------------------------------------------------------------- */ 122 : 123 : #if defined(MISSING_VSNPRINTF) 124 : char *pszBuffer = (char *) malloc(30000); 125 : if( vsprintf( pszBuffer, fmt, args) > 29998 ) 126 : { 127 : message = "PCIDSKException::vPrintf() ... buffer overrun."; 128 : } 129 : else 130 : message = pszBuffer; 131 : 132 : free( pszBuffer ); 133 : 134 : /* -------------------------------------------------------------------- */ 135 : /* This should grow a big enough buffer to hold any formatted */ 136 : /* result. */ 137 : /* -------------------------------------------------------------------- */ 138 : #else 139 : char szModestBuffer[500]; 140 : int nPR; 141 : va_list wrk_args; 142 : 143 : #ifdef va_copy 144 56 : va_copy( wrk_args, args ); 145 : #else 146 : wrk_args = args; 147 : #endif 148 : 149 56 : nPR = vsnprintf( szModestBuffer, sizeof(szModestBuffer), fmt, 150 : wrk_args ); 151 56 : if( nPR == -1 || nPR >= (int) sizeof(szModestBuffer)-1 ) 152 : { 153 0 : int nWorkBufferSize = 2000; 154 0 : PCIDSKBuffer oWorkBuffer(nWorkBufferSize); 155 : 156 : #ifdef va_copy 157 0 : va_end( wrk_args ); 158 0 : va_copy( wrk_args, args ); 159 : #else 160 : wrk_args = args; 161 : #endif 162 0 : while( (nPR=vsnprintf( oWorkBuffer.buffer, nWorkBufferSize, fmt, wrk_args)) 163 0 : >= nWorkBufferSize-1 164 0 : || nPR == -1 ) 165 : { 166 0 : nWorkBufferSize *= 4; 167 0 : oWorkBuffer.SetSize(nWorkBufferSize); 168 : #ifdef va_copy 169 0 : va_end( wrk_args ); 170 0 : va_copy( wrk_args, args ); 171 : #else 172 : wrk_args = args; 173 : #endif 174 : } 175 0 : message = oWorkBuffer.buffer; 176 : } 177 : else 178 : { 179 56 : message = szModestBuffer; 180 : } 181 56 : va_end( wrk_args ); 182 : #endif 183 56 : } 184 : 185 : /** 186 : * \fn const char *PCIDSKException::what() const throw(); 187 : * 188 : * \brief fetch exception message. 189 : * 190 : * @return a pointer to the internal message associated with the exception. 191 : */ 192 : 193 : #if defined(__clang__) && __clang_major__ == 3 && __clang_minor__ <= 2 194 : #pragma clang diagnostic push 195 : #pragma clang diagnostic ignored "-Wunknown-pragmas" 196 : #pragma clang diagnostic ignored "-Wdocumentation" 197 : #endif 198 : 199 : /** 200 : * \brief throw a formatted exception. 201 : * 202 : * This function throws a PCIDSK Exception by reference after formatting 203 : * the message using the given printf style format and arguments. This 204 : * function exists primarily so that throwing an exception can be done in 205 : * one line of code, instead of declaring an exception and then throwing it. 206 : * 207 : * @param fmt the printf style format (eg. "Illegal value:%d") 208 : * @param ... additional arguments as required by the format string. 209 : */ 210 40 : void PCIDSK::ThrowPCIDSKException( const char *fmt, ... ) 211 : 212 : { 213 : std::va_list args; 214 80 : PCIDSKException ex; 215 : 216 40 : va_start( args, fmt ); 217 40 : ex.vPrintf( fmt, args ); 218 40 : va_end( args ); 219 : 220 40 : throw ex; 221 : } 222 : 223 : #if defined(__clang__) && __clang_major__ == 3 && __clang_minor__ <= 2 224 : #pragma clang diagnostic pop 225 : #endif 226 : 227 : 228 15 : int PCIDSK::ThrowPCIDSKException( int /*ret_unused*/, const char *fmt, ... ) 229 : 230 : { 231 : std::va_list args; 232 30 : PCIDSKException ex; 233 : 234 15 : va_start( args, fmt ); 235 15 : ex.vPrintf( fmt, args ); 236 15 : va_end( args ); 237 : 238 15 : throw ex; 239 : } 240 : 241 1 : void* PCIDSK::ThrowPCIDSKExceptionPtr( const char *fmt, ... ) 242 : 243 : { 244 : std::va_list args; 245 2 : PCIDSKException ex; 246 : 247 1 : va_start( args, fmt ); 248 1 : ex.vPrintf( fmt, args ); 249 1 : va_end( args ); 250 : 251 1 : throw ex; 252 : }