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 : * Permission is hereby granted, free of charge, to any person obtaining a
10 : * copy of this software and associated documentation files (the "Software"),
11 : * to deal in the Software without restriction, including without limitation
12 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 : * and/or sell copies of the Software, and to permit persons to whom the
14 : * Software is furnished to do so, subject to the following conditions:
15 : *
16 : * The above copyright notice and this permission notice shall be included
17 : * in all copies or substantial portions of the Software.
18 : *
19 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 : * DEALINGS IN THE SOFTWARE.
26 : ****************************************************************************/
27 :
28 : #include "pcidsk_config.h"
29 : #include "pcidsk_types.h"
30 : #include "pcidsk_buffer.h"
31 : #include "pcidsk_exception.h"
32 : #include <cstdlib>
33 : #include <cstring>
34 : #include <cstdio>
35 : #include <cstdarg>
36 :
37 : #if !defined(va_copy) && defined(__va_copy)
38 : #define va_copy __va_copy
39 : #endif
40 :
41 : using PCIDSK::PCIDSKException;
42 :
43 : /**
44 :
45 : \class PCIDSK::PCIDSKException
46 :
47 : \brief Generic SDK Exception
48 :
49 : The PCIDSKException class is used for all errors thrown by the PCIDSK
50 : library. It includes a formatted message and is derived from std::exception.
51 : The PCIDSK library throws all exceptions as pointers, and library exceptions
52 : should be caught like this:
53 :
54 : @code
55 : try
56 : {
57 : PCIDSKFile *file = PCIDSK::Open( "irvine.pix, "r", NULL );
58 : }
59 : catch( PCIDSK::PCIDSKException &ex )
60 : {
61 : fprintf( stderr, "PCIDSKException:\n%s\n", ex.what() );
62 : exit( 1 );
63 : }
64 : @endcode
65 :
66 : */
67 :
68 : /************************************************************************/
69 : /* PCIDSKException() */
70 : /************************************************************************/
71 :
72 : #if defined(__clang__) && __clang_major__ == 3 && __clang_minor__ <= 2
73 : #pragma clang diagnostic push
74 : #pragma clang diagnostic ignored "-Wunknown-pragmas"
75 : #pragma clang diagnostic ignored "-Wdocumentation"
76 : #endif
77 :
78 :
79 : /**
80 : * Create exception with formatted message.
81 : *
82 : * This constructor supports formatting of an exception message
83 : * using printf style format and additional arguments.
84 : *
85 : * @param fmt the printf style format (eg. "Illegal value:%d")
86 : * @param ... additional arguments as required by the format string.
87 : */
88 :
89 0 : PCIDSKException::PCIDSKException( const char *fmt, ... )
90 :
91 : {
92 : std::va_list args;
93 :
94 0 : va_start( args, fmt );
95 0 : vPrintf( fmt, args );
96 0 : va_end( args );
97 0 : }
98 :
99 : #if defined(__clang__) && __clang_major__ == 3 && __clang_minor__ <= 2
100 : #pragma clang diagnostic pop
101 : #endif
102 :
103 : /************************************************************************/
104 : /* ~PCIDSKException() */
105 : /************************************************************************/
106 :
107 : /**
108 : * Destructor.
109 : */
110 :
111 112 : PCIDSKException::~PCIDSKException() throw()
112 :
113 : {
114 112 : }
115 :
116 : /************************************************************************/
117 : /* vPrintf() */
118 : /************************************************************************/
119 :
120 : /**
121 : * Format a message.
122 : *
123 : * Assigns a message to an exception using printf style formatting
124 : * and va_list arguments (similar to vfprintf().
125 : *
126 : * @param fmt printf style format string.
127 : * @param args additional arguments as required.
128 : */
129 :
130 :
131 56 : void PCIDSKException::vPrintf( const char *fmt, std::va_list args )
132 :
133 : {
134 : /* -------------------------------------------------------------------- */
135 : /* This implementation for platforms without vsnprintf() will */
136 : /* just plain fail if the formatted contents are too large. */
137 : /* -------------------------------------------------------------------- */
138 :
139 : #if defined(MISSING_VSNPRINTF)
140 : char *pszBuffer = (char *) malloc(30000);
141 : if( vsprintf( pszBuffer, fmt, args) > 29998 )
142 : {
143 : message = "PCIDSKException::vPrintf() ... buffer overrun.";
144 : }
145 : else
146 : message = pszBuffer;
147 :
148 : free( pszBuffer );
149 :
150 : /* -------------------------------------------------------------------- */
151 : /* This should grow a big enough buffer to hold any formatted */
152 : /* result. */
153 : /* -------------------------------------------------------------------- */
154 : #else
155 : char szModestBuffer[500];
156 : int nPR;
157 : va_list wrk_args;
158 :
159 : #ifdef va_copy
160 56 : va_copy( wrk_args, args );
161 : #else
162 : wrk_args = args;
163 : #endif
164 :
165 56 : nPR = vsnprintf( szModestBuffer, sizeof(szModestBuffer), fmt,
166 : wrk_args );
167 56 : if( nPR == -1 || nPR >= (int) sizeof(szModestBuffer)-1 )
168 : {
169 0 : int nWorkBufferSize = 2000;
170 0 : PCIDSKBuffer oWorkBuffer(nWorkBufferSize);
171 :
172 : #ifdef va_copy
173 0 : va_end( wrk_args );
174 0 : va_copy( wrk_args, args );
175 : #else
176 : wrk_args = args;
177 : #endif
178 0 : while( (nPR=vsnprintf( oWorkBuffer.buffer, nWorkBufferSize, fmt, wrk_args))
179 0 : >= nWorkBufferSize-1
180 0 : || nPR == -1 )
181 : {
182 0 : nWorkBufferSize *= 4;
183 0 : oWorkBuffer.SetSize(nWorkBufferSize);
184 : #ifdef va_copy
185 0 : va_end( wrk_args );
186 0 : va_copy( wrk_args, args );
187 : #else
188 : wrk_args = args;
189 : #endif
190 : }
191 0 : message = oWorkBuffer.buffer;
192 : }
193 : else
194 : {
195 56 : message = szModestBuffer;
196 : }
197 56 : va_end( wrk_args );
198 : #endif
199 56 : }
200 :
201 : /**
202 : * \fn const char *PCIDSKException::what() const throw();
203 : *
204 : * \brief fetch exception message.
205 : *
206 : * @return a pointer to the internal message associated with the exception.
207 : */
208 :
209 : #if defined(__clang__) && __clang_major__ == 3 && __clang_minor__ <= 2
210 : #pragma clang diagnostic push
211 : #pragma clang diagnostic ignored "-Wunknown-pragmas"
212 : #pragma clang diagnostic ignored "-Wdocumentation"
213 : #endif
214 :
215 : /**
216 : * \brief throw a formatted exception.
217 : *
218 : * This function throws a PCIDSK Exception by reference after formatting
219 : * the message using the given printf style format and arguments. This
220 : * function exists primarily so that throwing an exception can be done in
221 : * one line of code, instead of declaring an exception and then throwing it.
222 : *
223 : * @param fmt the printf style format (eg. "Illegal value:%d")
224 : * @param ... additional arguments as required by the format string.
225 : */
226 40 : void PCIDSK::ThrowPCIDSKException( const char *fmt, ... )
227 :
228 : {
229 : std::va_list args;
230 80 : PCIDSKException ex;
231 :
232 40 : va_start( args, fmt );
233 40 : ex.vPrintf( fmt, args );
234 40 : va_end( args );
235 :
236 40 : throw ex;
237 : }
238 :
239 : #if defined(__clang__) && __clang_major__ == 3 && __clang_minor__ <= 2
240 : #pragma clang diagnostic pop
241 : #endif
242 :
243 :
244 15 : int PCIDSK::ThrowPCIDSKException( int /*ret_unused*/, const char *fmt, ... )
245 :
246 : {
247 : std::va_list args;
248 30 : PCIDSKException ex;
249 :
250 15 : va_start( args, fmt );
251 15 : ex.vPrintf( fmt, args );
252 15 : va_end( args );
253 :
254 15 : throw ex;
255 : }
256 :
257 1 : void* PCIDSK::ThrowPCIDSKExceptionPtr( const char *fmt, ... )
258 :
259 : {
260 : std::va_list args;
261 2 : PCIDSKException ex;
262 :
263 1 : va_start( args, fmt );
264 1 : ex.vPrintf( fmt, args );
265 1 : va_end( args );
266 :
267 1 : throw ex;
268 : }
|