Line data Source code
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, 90 Allstate Parkway, Markham, Ontario, 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_config.h"
30 : #include "pcidsk_buffer.h"
31 : #include "pcidsk_exception.h"
32 : #include "core/pcidsk_utils.h"
33 :
34 : #include <cstdlib>
35 : #include <cstring>
36 : #include <cstdio>
37 : #include <sstream>
38 :
39 : using namespace PCIDSK;
40 :
41 : /************************************************************************/
42 : /* PCIDSKBuffer() */
43 : /************************************************************************/
44 :
45 13220 : PCIDSKBuffer::PCIDSKBuffer( int size )
46 :
47 : {
48 13220 : buffer_size = 0;
49 13220 : buffer = nullptr;
50 :
51 13220 : if( size > 0 )
52 7609 : SetSize( size );
53 13220 : }
54 :
55 : /************************************************************************/
56 : /* PCIDSKBuffer() */
57 : /************************************************************************/
58 :
59 2648 : PCIDSKBuffer::PCIDSKBuffer( const char *src, int size )
60 :
61 : {
62 2648 : buffer_size = 0;
63 2648 : buffer = nullptr;
64 :
65 2648 : SetSize( size );
66 2648 : memcpy( buffer, src, size );
67 2648 : }
68 :
69 : /************************************************************************/
70 : /* ~PCIDSKBuffer() */
71 : /************************************************************************/
72 :
73 31736 : PCIDSKBuffer::~PCIDSKBuffer()
74 :
75 : {
76 15868 : free( buffer );
77 15868 : }
78 :
79 : /************************************************************************/
80 : /* SetSize() */
81 : /************************************************************************/
82 :
83 14305 : void PCIDSKBuffer::SetSize( int size )
84 :
85 : {
86 14305 : if( size < 0 )
87 : {
88 0 : free( buffer );
89 0 : buffer = nullptr;
90 0 : buffer_size = 0;
91 0 : throw PCIDSKException( "Invalid buffer size: %d", size );
92 : }
93 14305 : buffer_size = size;
94 14305 : char* new_buffer = (char *) realloc(buffer,size+1);
95 :
96 14305 : if( new_buffer == nullptr )
97 : {
98 0 : free( buffer );
99 0 : buffer = nullptr;
100 0 : buffer_size = 0;
101 : throw PCIDSKException( "Out of memory allocating %d byte PCIDSKBuffer.",
102 0 : size );
103 : }
104 :
105 14305 : buffer = new_buffer;
106 14305 : buffer[size] = '\0';
107 14305 : }
108 :
109 : /************************************************************************/
110 : /* Get() */
111 : /************************************************************************/
112 :
113 13788 : const char *PCIDSKBuffer::Get( int offset, int size ) const
114 :
115 : {
116 13788 : Get( offset, size, work_field, 0 );
117 13788 : return work_field.c_str();
118 : }
119 :
120 : /************************************************************************/
121 : /* Get() */
122 : /************************************************************************/
123 :
124 32982 : void PCIDSKBuffer::Get( int offset, int size, std::string &target, int unpad ) const
125 :
126 : {
127 32982 : if( offset + size > buffer_size )
128 0 : return ThrowPCIDSKException( "Get() past end of PCIDSKBuffer." );
129 :
130 32982 : if( unpad )
131 : {
132 1161210 : while( size > 0 && buffer[offset+size-1] == ' ' )
133 1143200 : size--;
134 : }
135 :
136 32982 : target.assign( buffer + offset, size );
137 : }
138 :
139 : /************************************************************************/
140 : /* GetUInt64() */
141 : /************************************************************************/
142 :
143 535824 : uint64 PCIDSKBuffer::GetUInt64( int offset, int size ) const
144 :
145 : {
146 1071650 : std::string value_str;
147 :
148 535824 : if( offset + size > buffer_size )
149 0 : return ThrowPCIDSKException(0, "GetUInt64() past end of PCIDSKBuffer." );
150 :
151 535824 : value_str.assign( buffer + offset, size );
152 :
153 535824 : return atouint64(value_str.c_str());
154 : }
155 :
156 : /************************************************************************/
157 : /* GetInt() */
158 : /************************************************************************/
159 :
160 5958 : int PCIDSKBuffer::GetInt( int offset, int size ) const
161 :
162 : {
163 11916 : std::string value_str;
164 :
165 5958 : if( offset + size > buffer_size )
166 0 : return ThrowPCIDSKException(0, "GetInt() past end of PCIDSKBuffer." );
167 :
168 5958 : value_str.assign( buffer + offset, size );
169 :
170 5958 : return atoi(value_str.c_str());
171 : }
172 :
173 : /************************************************************************/
174 : /* GetDouble() */
175 : /************************************************************************/
176 :
177 5903 : double PCIDSKBuffer::GetDouble( int offset, int size ) const
178 :
179 : {
180 11806 : std::string value_str;
181 :
182 5903 : if( offset + size > buffer_size )
183 0 : return ThrowPCIDSKException(0, "GetDouble() past end of PCIDSKBuffer." );
184 :
185 5903 : value_str.assign( buffer + offset, size );
186 :
187 : /* -------------------------------------------------------------------- */
188 : /* PCIDSK uses FORTRAN 'D' format for doubles - convert to 'E' */
189 : /* (C style) before calling CPLAtof. */
190 : /* -------------------------------------------------------------------- */
191 : int i;
192 :
193 159381 : for( i = 0; i < size; i++ )
194 : {
195 153478 : if( value_str[i] == 'D' )
196 4883 : value_str[i] = 'E';
197 : }
198 :
199 5903 : return CPLAtof(value_str.c_str());
200 : }
201 :
202 : /************************************************************************/
203 : /* Put() */
204 : /************************************************************************/
205 :
206 43010 : void PCIDSKBuffer::Put( const char *value, int offset, int size, bool null_term )
207 :
208 : {
209 43010 : if( offset + size > buffer_size )
210 0 : return ThrowPCIDSKException( "Put() past end of PCIDSKBuffer." );
211 :
212 43010 : int v_size = static_cast<int>(strlen(value));
213 43010 : if( v_size > size )
214 51 : v_size = size;
215 :
216 43010 : if( v_size < size )
217 10941 : memset( buffer + offset, ' ', size );
218 :
219 43010 : memcpy( buffer + offset, value, v_size );
220 :
221 43010 : if (null_term)
222 : {
223 0 : *(buffer + offset + v_size) = '\0';
224 : }
225 : }
226 :
227 : /************************************************************************/
228 : /* PutBin(double) */
229 : /************************************************************************/
230 :
231 0 : void PCIDSKBuffer::PutBin(double value, int offset)
232 : {
233 0 : const char* pszValue = (const char*)&value;
234 0 : memcpy( buffer + offset, pszValue, 8 );
235 0 : }
236 :
237 : /************************************************************************/
238 : /* PutBin(int16) */
239 : /************************************************************************/
240 :
241 833 : void PCIDSKBuffer::PutBin(int16 value, int offset)
242 : {
243 833 : const char * pszValue = (const char *) &value;
244 :
245 833 : memcpy(buffer + offset, pszValue, sizeof(int16));
246 833 : }
247 :
248 : /************************************************************************/
249 : /* Put(uint64) */
250 : /************************************************************************/
251 :
252 16116 : void PCIDSKBuffer::Put( uint64 value, int offset, int size )
253 :
254 : {
255 : char fmt[64];
256 : char wrk[128];
257 :
258 16116 : snprintf( fmt, sizeof(fmt), "%%%d%sd", size, PCIDSK_FRMT_64_WITHOUT_PREFIX );
259 16116 : snprintf( wrk, sizeof(wrk), fmt, value );
260 :
261 16116 : Put( wrk, offset, size );
262 16116 : }
263 :
264 : /************************************************************************/
265 : /* Put(double) */
266 : /************************************************************************/
267 :
268 12386 : void PCIDSKBuffer::Put( double value, int offset, int size,
269 : const char *fmt )
270 :
271 : {
272 12386 : if( fmt == nullptr )
273 1088 : fmt = "%g";
274 :
275 : char wrk[128];
276 12386 : CPLsnprintf( wrk, 127, fmt, value );
277 :
278 12386 : char *exponent = strstr(wrk,"E");
279 12386 : if( exponent != nullptr )
280 10346 : *exponent = 'D';
281 :
282 12386 : Put( wrk, offset, size );
283 12386 : }
284 :
285 : /************************************************************************/
286 : /* operator=() */
287 : /************************************************************************/
288 :
289 0 : PCIDSKBuffer &PCIDSKBuffer::operator=( const PCIDSKBuffer &src )
290 :
291 : {
292 0 : if( this != &src )
293 : {
294 0 : SetSize( src.buffer_size );
295 0 : memcpy( buffer, src.buffer, buffer_size );
296 : }
297 :
298 0 : return *this;
299 : }
|