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