1 : /******************************************************************************
2 : *
3 : * Purpose: Implementation of the PCIDSKException class.
4 : *
5 : ******************************************************************************
6 : * Copyright (c) 2009
7 : * PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, 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_exception.h"
31 : #include <cstdlib>
32 : #include <cstring>
33 : #include <cstdio>
34 :
35 : using PCIDSK::PCIDSKException;
36 :
37 : #if defined(_MSC_VER) && (_MSC_VER < 1500)
38 : # define vsnprintf _vsnprintf
39 : #endif
40 :
41 : /**
42 :
43 : \class PCIDSK::PCIDSKException
44 :
45 : \brief Generic SDK Exception
46 :
47 : The PCIDSKException class is used for all errors thrown by the PCIDSK
48 : library. It includes a formatted message and is derived from std::exception.
49 : The PCIDSK library throws all exceptions as pointers, and library exceptions
50 : should be caught like this:
51 :
52 : @code
53 : try
54 : {
55 : PCIDSKFile *file = PCIDSK::Open( "irvine.pix, "r", NULL );
56 : }
57 : catch( PCIDSK::PCIDSKException &ex )
58 : {
59 : fprintf( stderr, "PCIDSKException:\n%s\n", ex.what() );
60 : exit( 1 );
61 : }
62 : @endcode
63 :
64 : */
65 :
66 : /************************************************************************/
67 : /* PCIDSKException() */
68 : /************************************************************************/
69 :
70 : /**
71 : * Create exception with formatted message.
72 : *
73 : * This constructor supports formatting of an exception message
74 : * using printf style format and additional arguments.
75 : *
76 : * @param fmt the printf style format (eg. "Illegal value:%d")
77 : * @param ... additional arguments as required by the format string.
78 : */
79 :
80 0 : PCIDSKException::PCIDSKException( const char *fmt, ... )
81 :
82 : {
83 : va_list args;
84 :
85 0 : va_start( args, fmt );
86 0 : vPrintf( fmt, args );
87 0 : va_end( args );
88 0 : }
89 :
90 : /************************************************************************/
91 : /* ~PCIDSKException() */
92 : /************************************************************************/
93 :
94 : /**
95 : * Destructor.
96 : */
97 :
98 0 : PCIDSKException::~PCIDSKException() throw()
99 :
100 : {
101 0 : }
102 :
103 : /************************************************************************/
104 : /* vPrintf() */
105 : /************************************************************************/
106 :
107 : /**
108 : * Format a message.
109 : *
110 : * Assigns a message to an exception using printf style formatting
111 : * and va_list arguments (similar to vfprintf().
112 : *
113 : * @param fmt printf style format string.
114 : * @param args additional arguments as required.
115 : */
116 :
117 :
118 0 : void PCIDSKException::vPrintf( const char *fmt, va_list args )
119 :
120 : {
121 : /* -------------------------------------------------------------------- */
122 : /* This implementation for platforms without vsnprintf() will */
123 : /* just plain fail if the formatted contents are too large. */
124 : /* -------------------------------------------------------------------- */
125 :
126 : #if defined(MISSING_VSNPRINTF)
127 : char *pszBuffer = (char *) malloc(30000);
128 : if( vsprintf( pszBuffer, fmt, args) > 29998 )
129 : {
130 : message = "PCIDSKException::vPrintf() ... buffer overrun.";
131 : }
132 : else
133 : message = pszBuffer;
134 :
135 : free( pszBuffer );
136 :
137 : /* -------------------------------------------------------------------- */
138 : /* This should grow a big enough buffer to hold any formatted */
139 : /* result. */
140 : /* -------------------------------------------------------------------- */
141 : #else
142 : char szModestBuffer[500];
143 : int nPR;
144 : va_list wrk_args;
145 :
146 : #ifdef va_copy
147 0 : va_copy( wrk_args, args );
148 : #else
149 : wrk_args = args;
150 : #endif
151 :
152 : nPR = vsnprintf( szModestBuffer, sizeof(szModestBuffer), fmt,
153 0 : wrk_args );
154 0 : if( nPR == -1 || nPR >= (int) sizeof(szModestBuffer)-1 )
155 : {
156 0 : int nWorkBufferSize = 2000;
157 0 : char *pszWorkBuffer = (char *) malloc(nWorkBufferSize);
158 :
159 : #ifdef va_copy
160 0 : va_end( wrk_args );
161 0 : va_copy( wrk_args, args );
162 : #else
163 : wrk_args = args;
164 : #endif
165 0 : while( (nPR=vsnprintf( pszWorkBuffer, nWorkBufferSize, fmt, wrk_args))
166 : >= nWorkBufferSize-1
167 : || nPR == -1 )
168 : {
169 0 : nWorkBufferSize *= 4;
170 : pszWorkBuffer = (char *) realloc(pszWorkBuffer,
171 0 : nWorkBufferSize );
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 : }
179 0 : message = pszWorkBuffer;
180 0 : free( pszWorkBuffer );
181 : }
182 : else
183 : {
184 0 : message = szModestBuffer;
185 : }
186 0 : va_end( wrk_args );
187 : #endif
188 0 : }
189 :
190 : /**
191 : * \fn const char *PCIDSKException::what() const throw();
192 : *
193 : * \brief fetch exception message.
194 : *
195 : * @return a pointer to the internal message associated with the exception.
196 : */
197 :
198 : /**
199 : * \brief throw a formatted exception.
200 : *
201 : * This function throws a PCIDSK Exception by reference after formatting
202 : * the message using the given printf style format and arguments. This
203 : * function exists primarily so that throwing an exception can be done in
204 : * one line of code, instead of declaring an exception and then throwing it.
205 : *
206 : * @param fmt the printf style format (eg. "Illegal value:%d")
207 : * @param ... additional arguments as required by the format string.
208 : */
209 0 : void PCIDSK::ThrowPCIDSKException( const char *fmt, ... )
210 :
211 : {
212 : va_list args;
213 0 : PCIDSKException ex("");
214 :
215 0 : va_start( args, fmt );
216 0 : ex.vPrintf( fmt, args );
217 0 : va_end( args );
218 :
219 0 : throw ex;
220 : }
|