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