1 : /******************************************************************************
2 : *
3 : * Purpose: Implementation of the PCIDSKBuffer class. This class is for
4 : * convenient parsing and formatting of PCIDSK ASCII headers.
5 : *
6 : ******************************************************************************
7 : * Copyright (c) 2009
8 : * PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, Canada
9 : *
10 : * Permission is hereby granted, free of charge, to any person obtaining a
11 : * copy of this software and associated documentation files (the "Software"),
12 : * to deal in the Software without restriction, including without limitation
13 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 : * and/or sell copies of the Software, and to permit persons to whom the
15 : * Software is furnished to do so, subject to the following conditions:
16 : *
17 : * The above copyright notice and this permission notice shall be included
18 : * in all copies or substantial portions of the Software.
19 : *
20 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 : * DEALINGS IN THE SOFTWARE.
27 : ****************************************************************************/
28 :
29 : #include "pcidsk_buffer.h"
30 : #include "pcidsk_exception.h"
31 : #include "core/pcidsk_utils.h"
32 :
33 : #include <cstdlib>
34 : #include <cstring>
35 : #include <cstdio>
36 : #include <sstream>
37 :
38 : using namespace PCIDSK;
39 :
40 : #ifdef _MSC_VER
41 : #ifndef snprintf
42 : #define snprintf _snprintf
43 : #endif // !defined(snprintf)
44 : #endif
45 :
46 : /************************************************************************/
47 : /* PCIDSKBuffer() */
48 : /************************************************************************/
49 :
50 1615 : PCIDSKBuffer::PCIDSKBuffer( int size )
51 :
52 : {
53 1615 : buffer_size = 0;
54 1615 : buffer = NULL;
55 :
56 1615 : if( size > 0 )
57 1099 : SetSize( size );
58 1615 : }
59 :
60 : /************************************************************************/
61 : /* PCIDSKBuffer() */
62 : /************************************************************************/
63 :
64 170 : PCIDSKBuffer::PCIDSKBuffer( const char *src, int size )
65 :
66 : {
67 170 : buffer_size = 0;
68 170 : buffer = NULL;
69 :
70 170 : SetSize( size );
71 170 : memcpy( buffer, src, size );
72 170 : }
73 :
74 : /************************************************************************/
75 : /* ~PCIDSKBuffer() */
76 : /************************************************************************/
77 :
78 1785 : PCIDSKBuffer::~PCIDSKBuffer()
79 :
80 : {
81 1785 : free( buffer );
82 1785 : }
83 :
84 : /************************************************************************/
85 : /* SetSize() */
86 : /************************************************************************/
87 :
88 2633 : void PCIDSKBuffer::SetSize( int size )
89 :
90 : {
91 2633 : buffer_size = size;
92 2633 : if( buffer == NULL )
93 1743 : buffer = (char *) malloc(size+1);
94 : else
95 890 : buffer = (char *) realloc(buffer,size+1);
96 :
97 2633 : if( buffer == NULL )
98 : {
99 0 : buffer_size = 0;
100 : ThrowPCIDSKException( "Out of memory allocating %d byte PCIDSKBuffer.",
101 0 : size );
102 : }
103 :
104 2633 : buffer[size] = '\0';
105 2633 : }
106 :
107 : /************************************************************************/
108 : /* Get() */
109 : /************************************************************************/
110 :
111 2350 : const char *PCIDSKBuffer::Get( int offset, int size ) const
112 :
113 : {
114 2350 : Get( offset, size, work_field, 0 );
115 2350 : return work_field.c_str();
116 : }
117 :
118 : /************************************************************************/
119 : /* Get() */
120 : /************************************************************************/
121 :
122 6526 : void PCIDSKBuffer::Get( int offset, int size, std::string &target, int unpad ) const
123 :
124 : {
125 6526 : if( offset + size > buffer_size )
126 0 : ThrowPCIDSKException( "Get() past end of PCIDSKBuffer." );
127 :
128 6526 : if( unpad )
129 : {
130 252763 : while( size > 0 && buffer[offset+size-1] == ' ' )
131 244465 : size--;
132 : }
133 :
134 6526 : target.assign( buffer + offset, size );
135 6526 : }
136 :
137 : /************************************************************************/
138 : /* GetUInt64() */
139 : /************************************************************************/
140 :
141 305 : uint64 PCIDSKBuffer::GetUInt64( int offset, int size ) const
142 :
143 : {
144 305 : std::string value_str;
145 :
146 305 : if( offset + size > buffer_size )
147 0 : ThrowPCIDSKException( "GetUInt64() past end of PCIDSKBuffer." );
148 :
149 305 : value_str.assign( buffer + offset, size );
150 :
151 305 : return atouint64(value_str.c_str());
152 : }
153 :
154 : /************************************************************************/
155 : /* GetInt() */
156 : /************************************************************************/
157 :
158 1396 : int PCIDSKBuffer::GetInt( int offset, int size ) const
159 :
160 : {
161 1396 : std::string value_str;
162 :
163 1396 : if( offset + size > buffer_size )
164 0 : ThrowPCIDSKException( "GetInt() past end of PCIDSKBuffer." );
165 :
166 1396 : value_str.assign( buffer + offset, size );
167 :
168 1396 : return atoi(value_str.c_str());
169 : }
170 :
171 : /************************************************************************/
172 : /* GetDouble() */
173 : /************************************************************************/
174 :
175 3949 : double PCIDSKBuffer::GetDouble( int offset, int size ) const
176 :
177 : {
178 3949 : std::string value_str;
179 :
180 3949 : if( offset + size > buffer_size )
181 0 : ThrowPCIDSKException( "GetDouble() past end of PCIDSKBuffer." );
182 :
183 3949 : value_str.assign( buffer + offset, size );
184 :
185 : /* -------------------------------------------------------------------- */
186 : /* PCIDSK uses FORTRAN 'D' format for doubles - convert to 'E' */
187 : /* (C style) before calling atof. */
188 : /* -------------------------------------------------------------------- */
189 : int i;
190 :
191 106623 : for( i = 0; i < size; i++ )
192 : {
193 102674 : if( value_str[i] == 'D' )
194 3184 : value_str[i] = 'E';
195 : }
196 :
197 3949 : std::stringstream oStream;
198 3949 : oStream << value_str;
199 3949 : double dValue = 0.0;
200 3949 : oStream >> dValue;
201 :
202 3949 : return dValue;
203 : // return atof(value_str.c_str());
204 : }
205 :
206 : /************************************************************************/
207 : /* Put() */
208 : /************************************************************************/
209 :
210 13348 : void PCIDSKBuffer::Put( const char *value, int offset, int size, bool null_term )
211 :
212 : {
213 13348 : if( offset + size > buffer_size )
214 0 : ThrowPCIDSKException( "Put() past end of PCIDSKBuffer." );
215 :
216 13348 : int v_size = strlen(value);
217 13348 : if( v_size > size )
218 0 : v_size = size;
219 :
220 13348 : if( v_size < size )
221 2368 : memset( buffer + offset, ' ', size );
222 :
223 13348 : memcpy( buffer + offset, value, v_size );
224 :
225 13348 : if (null_term)
226 : {
227 0 : *(buffer + offset + v_size) = '\0';
228 : }
229 13348 : }
230 :
231 : /************************************************************************/
232 : /* PutBin(double) */
233 : /************************************************************************/
234 :
235 0 : void PCIDSKBuffer::PutBin(double value, int offset)
236 : {
237 0 : const char* pszValue = (const char*)&value;
238 0 : memcpy( buffer + offset, pszValue, 8 );
239 0 : }
240 :
241 : /************************************************************************/
242 : /* Put(uint64) */
243 : /************************************************************************/
244 :
245 2803 : void PCIDSKBuffer::Put( uint64 value, int offset, int size )
246 :
247 : {
248 : char fmt[64];
249 : char wrk[128];
250 :
251 2803 : sprintf( fmt, "%%%d%sd", size, PCIDSK_FRMT_64_WITHOUT_PREFIX );
252 2803 : sprintf( wrk, fmt, value );
253 :
254 2803 : Put( wrk, offset, size );
255 2803 : }
256 :
257 : /************************************************************************/
258 : /* Put(double) */
259 : /************************************************************************/
260 :
261 7471 : void PCIDSKBuffer::Put( double value, int offset, int size,
262 : const char *fmt )
263 :
264 : {
265 7471 : if( fmt == NULL )
266 7 : fmt = "%g";
267 :
268 : char wrk[128];
269 7471 : snprintf( wrk, 127, fmt, value );
270 :
271 7471 : char *exponent = strstr(wrk,"E");
272 7471 : if( exponent != NULL )
273 6716 : *exponent = 'D';
274 :
275 7471 : Put( wrk, offset, size );
276 7471 : }
277 :
278 : /************************************************************************/
279 : /* operator=() */
280 : /************************************************************************/
281 :
282 2 : PCIDSKBuffer &PCIDSKBuffer::operator=( const PCIDSKBuffer &src )
283 :
284 : {
285 2 : SetSize( src.buffer_size );
286 2 : memcpy( buffer, src.buffer, buffer_size );
287 :
288 2 : return *this;
289 : }
|