1 /******************************************************************************
2 * $Id: ceos.c 3b0bbf7a8a012d69a783ee1f9cfeb5c52b370021 2017-06-27 20:57:02Z Even Rouault $
3 *
4 * Project: ASI CEOS Translator
5 * Purpose: Core CEOS functions.
6 * Author: Paul Lahaie, pjlahaie@atlsci.com
7 *
8 ******************************************************************************
9 * Copyright (c) 2000, Atlantis Scientific Inc
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a
12 * copy of this software and associated documentation files (the "Software"),
13 * to deal in the Software without restriction, including without limitation
14 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 * and/or sell copies of the Software, and to permit persons to whom the
16 * Software is furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included
19 * in all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 * DEALINGS IN THE SOFTWARE.
28 ****************************************************************************/
29
30 #include "ceos.h"
31
32 CPL_CVSID("$Id: ceos.c 3b0bbf7a8a012d69a783ee1f9cfeb5c52b370021 2017-06-27 20:57:02Z Even Rouault $")
33
34 /* Function implementations of functions described in ceos.h */
35
36 void CeosUpdateHeaderFromBuffer(CeosRecord_t *record);
37
InitEmptyCeosRecord(CeosRecord_t * record,int32 sequence,CeosTypeCode_t typecode,int32 length)38 void InitEmptyCeosRecord(CeosRecord_t *record, int32 sequence, CeosTypeCode_t typecode, int32 length)
39 {
40 if(record)
41 {
42 if((record->Buffer = HMalloc(length)) == NULL)
43 {
44 return;
45 }
46 /* First we zero fill the buffer */
47 memset(record->Buffer,0,length);
48
49 /* Setup values inside the CeosRecord_t header */
50 record->Sequence = sequence;
51 record->Flavor = 0;
52 record->FileId = 0;
53 record->TypeCode = typecode;
54 record->Subsequence = 0;
55 record->Length = length;
56
57 /* Now we fill in the buffer portion as well */
58 NativeToCeos( record->Buffer+SEQUENCE_OFF, &(record->Sequence), sizeof(record->Sequence), sizeof( record->Sequence ) );
59 memcpy(record->Buffer+TYPE_OFF, &( record->TypeCode.Int32Code ), sizeof( record->TypeCode.Int32Code ) );
60 NativeToCeos( record->Buffer+LENGTH_OFF, &length, sizeof( length ), sizeof( length ) );
61 }
62 }
63
InitCeosRecord(CeosRecord_t * record,uchar * buffer)64 void InitCeosRecord(CeosRecord_t *record, uchar *buffer)
65 {
66 if(record && buffer)
67 {
68 InitCeosRecordWithHeader(record, buffer, buffer+CEOS_HEADER_LENGTH);
69 }
70 }
71
InitCeosRecordWithHeader(CeosRecord_t * record,uchar * header,uchar * buffer)72 void InitCeosRecordWithHeader(CeosRecord_t *record, uchar *header, uchar *buffer)
73 {
74 if(record && buffer && header)
75 {
76 if( record->Length != 0 )
77 record->Length = DetermineCeosRecordBodyLength( header );
78
79 if(record->Length < CEOS_HEADER_LENGTH ||
80 (record->Buffer = HMalloc(record->Length)) == NULL)
81 {
82 record->Length = 0;
83 return;
84 }
85
86 /* First copy the header then the buffer */
87 memcpy(record->Buffer,header,CEOS_HEADER_LENGTH);
88 /* Now we copy the rest */
89 if( record->Length > CEOS_HEADER_LENGTH )
90 memcpy(record->Buffer+CEOS_HEADER_LENGTH,buffer,record->Length-CEOS_HEADER_LENGTH);
91
92 /* Now we fill in the rest of the structure! */
93 memcpy(&(record->TypeCode.Int32Code),header+TYPE_OFF,sizeof(record->TypeCode.Int32Code));
94 CeosToNative(&(record->Sequence),header+SEQUENCE_OFF,sizeof(record->Sequence), sizeof( record->Sequence ) );
95 }
96 }
97
DetermineCeosRecordBodyLength(const uchar * header)98 int DetermineCeosRecordBodyLength(const uchar *header)
99 {
100 int i;
101
102 if(header)
103 {
104 CeosToNative(&i,header+LENGTH_OFF,sizeof( i ), sizeof( i ) );
105
106 return i;
107 }
108
109 return -1;
110 }
111
DeleteCeosRecord(CeosRecord_t * record)112 void DeleteCeosRecord(CeosRecord_t *record)
113 {
114 if(record)
115 {
116 if(record->Buffer)
117 {
118 HFree(record->Buffer);
119 record->Buffer = NULL;
120 }
121 HFree( record );
122 }
123 }
124
GetCeosRecordStruct(const CeosRecord_t * record,void * struct_ptr)125 void GetCeosRecordStruct(const CeosRecord_t *record,void *struct_ptr)
126 {
127 if(record && struct_ptr && record->Buffer)
128 {
129 memcpy(record->Buffer,struct_ptr,record->Length);
130 }
131 }
132
PutCeosRecordStruct(CeosRecord_t * record,const void * struct_ptr)133 void PutCeosRecordStruct(CeosRecord_t *record,const void *struct_ptr)
134 {
135 int Length;
136
137 if(record && struct_ptr)
138 {
139 CeosToNative( &Length, struct_ptr, sizeof( Length ), sizeof( Length ) );
140 memcpy(record->Buffer,struct_ptr,Length);
141 CeosUpdateHeaderFromBuffer(record);
142 }
143 }
144
GetCeosField(CeosRecord_t * record,int32 start_byte,const char * format,void * value)145 void GetCeosField(CeosRecord_t *record, int32 start_byte,
146 const char *format, void *value)
147 {
148 int field_size;
149 char *d_ptr;
150 char *mod_buf = NULL;
151
152 field_size = atoi(format+1);
153
154 if(field_size < 1)
155 {
156 return;
157 }
158
159 /* Check for out of bounds */
160 if(start_byte + field_size - 1 > record->Length)
161 {
162 return;
163 }
164
165 if((mod_buf = (char *) HMalloc(field_size + 1)) == NULL)
166 {
167 return;
168 }
169
170 memcpy(mod_buf,record->Buffer+(start_byte-1), field_size);
171 mod_buf[field_size] = '\0';
172
173 /* Switch on format type */
174 switch(format[0])
175 {
176 case 'b':
177 case 'B':
178 /* Binary data type */
179 if(field_size > 1)
180 {
181 CeosToNative( value, mod_buf, field_size, field_size );
182 } else {
183 memcpy( value, mod_buf, field_size );
184 }
185 break;
186
187 case 'i':
188 case 'I':
189 /* Integer type */
190 *( (int *)value) = atoi(mod_buf);
191 break;
192
193 case 'f':
194 case 'F':
195 case 'e':
196 case 'E':
197 /* Double precision float data type */
198
199 /* Change the 'D' exponent separators to 'e' */
200 if( ( d_ptr = strchr(mod_buf, 'd') ) != NULL)
201 {
202 *d_ptr = 'e';
203 }
204 if( ( d_ptr = strchr(mod_buf, 'D') ) != NULL)
205 {
206 *d_ptr = 'e';
207 }
208
209 *( (double *)value) = strtod(mod_buf,NULL);
210 break;
211 case 'a':
212 case 'A':
213 /* ASCII.. We just easily extract it */
214 ( (char *)value)[field_size] = '\0';
215 memcpy( value, mod_buf, field_size );
216 break;
217
218 default:
219 /* Unknown format. Do nothing. */
220 break;
221 }
222
223 HFree(mod_buf);
224 }
225
SetCeosField(CeosRecord_t * record,int32 start_byte,char * format,void * value)226 void SetCeosField(CeosRecord_t *record, int32 start_byte, char *format, void *value)
227 {
228 int field_size;
229 char * temp_buf = NULL;
230 char szPrintfFormat[ 20 ];
231
232 field_size = 0;
233 sscanf(&format[1], "%d", &field_size);
234 if(field_size < 1)
235 {
236 return;
237 }
238
239 /* Check for bounds */
240 if(start_byte + field_size - 1 > record->Length)
241 {
242 return;
243 }
244
245 /* Make a local buffer to print into */
246 if((temp_buf = (char *) HMalloc(field_size+1)) == NULL)
247 {
248 return;
249 }
250 switch(format[0])
251 {
252 case 'b':
253 case 'B':
254 /* Binary data type */
255 if(field_size > 1)
256 {
257 NativeToCeos( value, temp_buf, field_size, field_size );
258 } else {
259 memcpy(value,temp_buf,field_size);
260 }
261 break;
262
263 case 'i':
264 case 'I':
265 /* Integer data type */
266 snprintf( szPrintfFormat, sizeof(szPrintfFormat), "%%%s%c",format+1, 'd');
267 snprintf( temp_buf, field_size+1, szPrintfFormat, *(int *) value);
268 break;
269
270 case 'f':
271 case 'F':
272 /* Double precision floating point data type */
273 snprintf( szPrintfFormat, sizeof(szPrintfFormat), "%%%s%c", format+1, 'g');
274 snprintf( temp_buf, field_size+1, szPrintfFormat, *(double *)value);
275 break;
276
277 case 'e':
278 case 'E':
279 /* Double precision floating point data type (forced exponent) */
280 snprintf( szPrintfFormat, sizeof(szPrintfFormat), "%%%s%c", format+1, 'e');
281 snprintf( temp_buf, field_size+1, szPrintfFormat, *(double *)value);
282 break;
283
284 case 'a':
285 case 'A':
286 strncpy(temp_buf,value,field_size+1);
287 temp_buf[field_size] = '0';
288 break;
289
290 default:
291 /* Unknown format */
292 HFree(temp_buf);
293 return;
294 }
295
296 memcpy(record->Buffer + start_byte -1, temp_buf, field_size);
297
298 HFree(temp_buf);
299 }
300
SetIntCeosField(CeosRecord_t * record,int32 start_byte,int32 length,int32 value)301 void SetIntCeosField(CeosRecord_t *record, int32 start_byte, int32 length, int32 value)
302 {
303 int integer_value = value;
304 char total_len[12]; /* 12 because 2^32 -> 4294967296 + I + null */
305
306 snprintf(total_len,sizeof(total_len),"I%d",length);
307 SetCeosField(record,start_byte,total_len,&integer_value);
308 }
309
FindCeosRecord(Link_t * record_list,CeosTypeCode_t typecode,int32 fileid,int32 flavor,int32 subsequence)310 CeosRecord_t *FindCeosRecord(Link_t *record_list, CeosTypeCode_t typecode, int32 fileid, int32 flavor, int32 subsequence)
311 {
312 Link_t *Link;
313 CeosRecord_t *record;
314
315 for( Link = record_list; Link != NULL; Link = Link->next )
316 {
317 record = (CeosRecord_t *)Link->object;
318
319 if( (record->TypeCode.Int32Code == typecode.Int32Code)
320 && ( ( fileid == -1 ) || ( record->FileId == fileid ) )
321 && ( ( flavor == -1 ) || ( record->Flavor == flavor ) )
322 && ( ( subsequence == -1 ) || ( record->Subsequence == subsequence ) ) )
323 return record;
324 }
325
326 return NULL;
327 }
328
CPL_IGNORE_RET_VAL_SIZET(CPL_UNUSED size_t unused)329 CPL_INLINE static void CPL_IGNORE_RET_VAL_SIZET(CPL_UNUSED size_t unused) {}
330
SerializeCeosRecordsToFile(Link_t * record_list,VSILFILE * fp)331 void SerializeCeosRecordsToFile(Link_t *record_list, VSILFILE *fp)
332 {
333 Link_t *list;
334 CeosRecord_t crec;
335 unsigned char *Buffer;
336
337 list = record_list;
338
339 while(list != NULL)
340 {
341 memcpy(&crec,list->object,sizeof(CeosRecord_t));
342 Buffer = crec.Buffer;
343 crec.Buffer = NULL;
344 CPL_IGNORE_RET_VAL_SIZET(VSIFWriteL(&crec,sizeof(CeosRecord_t),1,fp));
345 CPL_IGNORE_RET_VAL_SIZET(VSIFWriteL(Buffer,crec.Length,1,fp));
346 }
347 }
348
SerializeCeosRecordsFromFile(Link_t * record_list,VSILFILE * fp)349 void SerializeCeosRecordsFromFile(Link_t *record_list, VSILFILE *fp)
350 {
351 CeosRecord_t *crec;
352 Link_t *Link;
353
354 while(!VSIFEofL(fp))
355 {
356 crec = HMalloc(sizeof(CeosRecord_t));
357 CPL_IGNORE_RET_VAL_SIZET(VSIFReadL(crec,sizeof(CeosRecord_t),1,fp));
358 crec->Buffer = HMalloc(crec->Length * sizeof(char) );
359 CPL_IGNORE_RET_VAL_SIZET(VSIFReadL(crec->Buffer,sizeof(char),crec->Length,fp));
360 Link = ceos2CreateLink(crec);
361 AddLink(record_list,Link);
362 }
363 }
364
CeosUpdateHeaderFromBuffer(CeosRecord_t * record)365 void CeosUpdateHeaderFromBuffer(CeosRecord_t *record)
366 {
367 if(record && record->Buffer)
368 {
369 CeosToNative( &( record->Length ), record->Buffer+LENGTH_OFF, sizeof(record->Length ), sizeof( record->Length ) );
370 memcpy(&(record->TypeCode.Int32Code),record->Buffer+TYPE_OFF,sizeof(record->TypeCode.Int32Code));
371 CeosToNative(&(record->Sequence),record->Buffer+SEQUENCE_OFF,sizeof(record->Sequence ), sizeof( record->Sequence ) );
372 }
373 if(record)
374 record->Subsequence = 0;
375 }
376
377 #ifdef CPL_LSB
378
379 static
swapbyte(void * dst,void * src,size_t toswap)380 void swapbyte(void *dst,void *src,size_t toswap)
381 {
382 size_t i,e;
383 unsigned char *in = (unsigned char *) src;
384 unsigned char *out = (unsigned char *) dst;
385
386 for(i = 0,e=toswap;i < toswap;i++,e--)
387 {
388 out[i] = in[e-1];
389 }
390 }
391
NativeToCeos(void * dst,const void * src,const size_t len,const size_t swapunit)392 void NativeToCeos( void *dst, const void *src, const size_t len, const size_t swapunit)
393 {
394 size_t i;
395 size_t l_remainder;
396 size_t units;
397
398
399 l_remainder = len % swapunit;
400
401 units = len - l_remainder;
402
403 for(i = 0;i < units; i += swapunit )
404 {
405 swapbyte( ( unsigned char *) dst + i, ( unsigned char * ) src + i, swapunit);
406 }
407
408 if(l_remainder)
409 {
410 memcpy( ( unsigned char * ) dst + i, ( unsigned char * ) src + i, l_remainder );
411 }
412 }
413
414 #endif
415