Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: ASI CEOS Translator
4 : * Purpose: Core CEOS functions.
5 : * Author: Paul Lahaie, pjlahaie@atlsci.com
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2000, Atlantis Scientific Inc
9 : *
10 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #include "ceos.h"
14 :
15 : #include "cpl_error.h"
16 : #include <assert.h>
17 :
18 : /* Function implementations of functions described in ceos.h */
19 :
20 : void CeosUpdateHeaderFromBuffer(CeosRecord_t *record);
21 :
22 0 : void InitEmptyCeosRecord(CeosRecord_t *record, int32 sequence,
23 : CeosTypeCode_t typecode, int32 length)
24 : {
25 0 : if (record)
26 : {
27 0 : if ((record->Buffer = HMalloc(length)) == NULL)
28 : {
29 0 : return;
30 : }
31 : /* First we zero fill the buffer */
32 0 : memset(record->Buffer, 0, length);
33 :
34 : /* Setup values inside the CeosRecord_t header */
35 0 : record->Sequence = sequence;
36 0 : record->Flavor = 0;
37 0 : record->FileId = 0;
38 0 : record->TypeCode = typecode;
39 0 : record->Subsequence = 0;
40 0 : record->Length = length;
41 :
42 : /* Now we fill in the buffer portion as well */
43 0 : NativeToCeos(record->Buffer + SEQUENCE_OFF, &(record->Sequence),
44 : sizeof(record->Sequence), sizeof(record->Sequence));
45 0 : memcpy(record->Buffer + TYPE_OFF, &(record->TypeCode.Int32Code),
46 : sizeof(record->TypeCode.Int32Code));
47 0 : NativeToCeos(record->Buffer + LENGTH_OFF, &length, sizeof(length),
48 : sizeof(length));
49 : }
50 : }
51 :
52 0 : void InitCeosRecord(CeosRecord_t *record, uchar *buffer)
53 : {
54 0 : if (record && buffer)
55 : {
56 0 : InitCeosRecordWithHeader(record, buffer, buffer + CEOS_HEADER_LENGTH);
57 : }
58 0 : }
59 :
60 102 : void InitCeosRecordWithHeader(CeosRecord_t *record, uchar *header,
61 : uchar *buffer)
62 : {
63 102 : if (record && buffer && header)
64 : {
65 102 : if (record->Length != 0)
66 102 : record->Length = DetermineCeosRecordBodyLength(header);
67 :
68 102 : if (record->Length < CEOS_HEADER_LENGTH ||
69 102 : (record->Buffer = HMalloc(record->Length)) == NULL)
70 : {
71 0 : record->Length = 0;
72 0 : return;
73 : }
74 :
75 : /* First copy the header then the buffer */
76 102 : memcpy(record->Buffer, header, CEOS_HEADER_LENGTH);
77 : /* Now we copy the rest */
78 102 : if (record->Length > CEOS_HEADER_LENGTH)
79 102 : memcpy(record->Buffer + CEOS_HEADER_LENGTH, buffer,
80 102 : record->Length - CEOS_HEADER_LENGTH);
81 :
82 : /* Now we fill in the rest of the structure! */
83 102 : memcpy(&(record->TypeCode.Int32Code), header + TYPE_OFF,
84 : sizeof(record->TypeCode.Int32Code));
85 102 : CeosToNative(&(record->Sequence), header + SEQUENCE_OFF,
86 : sizeof(record->Sequence), sizeof(record->Sequence));
87 : }
88 : }
89 :
90 206 : int DetermineCeosRecordBodyLength(const uchar *header)
91 : {
92 : int i;
93 :
94 206 : if (header)
95 : {
96 206 : CeosToNative(&i, header + LENGTH_OFF, sizeof(i), sizeof(i));
97 206 : return i;
98 : }
99 :
100 0 : return -1;
101 : }
102 :
103 102 : void DeleteCeosRecord(CeosRecord_t *record)
104 : {
105 102 : if (record)
106 : {
107 102 : if (record->Buffer)
108 : {
109 102 : HFree(record->Buffer);
110 102 : record->Buffer = NULL;
111 : }
112 102 : HFree(record);
113 : }
114 102 : }
115 :
116 0 : void GetCeosRecordStruct(const CeosRecord_t *record, void *struct_ptr)
117 : {
118 0 : if (record && struct_ptr && record->Buffer)
119 : {
120 0 : memcpy(record->Buffer, struct_ptr, record->Length);
121 : }
122 0 : }
123 :
124 0 : void PutCeosRecordStruct(CeosRecord_t *record, const void *struct_ptr)
125 : {
126 : int Length;
127 :
128 0 : if (record && struct_ptr)
129 : {
130 0 : CeosToNative(&Length, struct_ptr, sizeof(Length), sizeof(Length));
131 0 : memcpy(record->Buffer, struct_ptr, Length);
132 0 : CeosUpdateHeaderFromBuffer(record);
133 : }
134 0 : }
135 :
136 1167 : void GetCeosField(const CeosRecord_t *record, int32 start_byte,
137 : const char *format, void *value)
138 : {
139 : char *d_ptr;
140 1167 : char *mod_buf = NULL;
141 :
142 1167 : const int field_size = atoi(format + 1);
143 1167 : assert(field_size >= 1);
144 :
145 1167 : if (format[0] == 'a' || format[0] == 'A')
146 : {
147 1085 : ((char *)value)[0] = 0;
148 1085 : ((char *)value)[field_size] = 0;
149 : }
150 :
151 : /* Check for out of bounds */
152 1167 : if (start_byte + field_size - 1 > record->Length)
153 : {
154 0 : CPLError(CE_Failure, CPLE_AppDefined,
155 : "Cannot read field. Would require record to be at least %d "
156 : "bytes large, whereas it is only %d",
157 0 : start_byte + field_size - 1, record->Length);
158 0 : return;
159 : }
160 :
161 1167 : if ((mod_buf = (char *)HMalloc(field_size + 1)) == NULL)
162 : {
163 0 : return;
164 : }
165 :
166 1167 : memcpy(mod_buf, record->Buffer + (start_byte - 1), field_size);
167 1167 : mod_buf[field_size] = 0;
168 :
169 : /* Switch on format type */
170 1167 : switch (format[0])
171 : {
172 18 : case 'b':
173 : case 'B':
174 : /* Binary data type */
175 18 : if (field_size > 1)
176 : {
177 18 : CeosToNative(value, mod_buf, field_size, field_size);
178 : }
179 : else
180 : {
181 0 : memcpy(value, mod_buf, field_size);
182 : }
183 18 : break;
184 :
185 64 : case 'i':
186 : case 'I':
187 : /* Integer type */
188 64 : *((int *)value) = atoi(mod_buf);
189 64 : break;
190 :
191 0 : case 'f':
192 : case 'F':
193 : case 'e':
194 : case 'E':
195 : /* Double precision float data type */
196 :
197 : /* Change the 'D' exponent separators to 'e' */
198 0 : if ((d_ptr = strchr(mod_buf, 'd')) != NULL)
199 : {
200 0 : *d_ptr = 'e';
201 : }
202 0 : if ((d_ptr = strchr(mod_buf, 'D')) != NULL)
203 : {
204 0 : *d_ptr = 'e';
205 : }
206 :
207 0 : *((double *)value) = strtod(mod_buf, NULL);
208 0 : break;
209 1085 : case 'a':
210 : case 'A':
211 : /* ASCII.. We just easily extract it */
212 1085 : ((char *)value)[field_size] = '\0';
213 1085 : memcpy(value, mod_buf, field_size);
214 1085 : break;
215 :
216 0 : default:
217 : /* Unknown format. Do nothing. */
218 0 : break;
219 : }
220 :
221 1167 : HFree(mod_buf);
222 : }
223 :
224 0 : void SetCeosField(CeosRecord_t *record, int32 start_byte, const char *format,
225 : int intValue, double dblValue)
226 : {
227 : int field_size;
228 0 : char *temp_buf = NULL;
229 : char szPrintfFormat[20];
230 :
231 0 : field_size = 0;
232 0 : sscanf(&format[1], "%d", &field_size);
233 0 : if (field_size < 1)
234 : {
235 0 : return;
236 : }
237 :
238 : /* Check for bounds */
239 0 : if (start_byte + field_size - 1 > record->Length)
240 : {
241 0 : return;
242 : }
243 :
244 : /* Make a local buffer to print into */
245 0 : if ((temp_buf = (char *)HMalloc(field_size + 1)) == NULL)
246 : {
247 0 : return;
248 : }
249 0 : switch (format[0])
250 : {
251 0 : case 'b':
252 : case 'B':
253 : #if 0
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 : #endif
263 0 : fprintf(stderr, "SetCeosField with format=%c not implemented",
264 0 : format[0]);
265 0 : HFree(temp_buf);
266 0 : return;
267 :
268 0 : case 'i':
269 : case 'I':
270 : /* Integer data type */
271 0 : snprintf(szPrintfFormat, sizeof(szPrintfFormat), "%%%s%c",
272 : format + 1, 'd');
273 0 : snprintf(temp_buf, field_size + 1, szPrintfFormat, intValue);
274 0 : break;
275 :
276 0 : case 'f':
277 : case 'F':
278 : /* Double precision floating point data type */
279 0 : snprintf(szPrintfFormat, sizeof(szPrintfFormat), "%%%s%c",
280 : format + 1, 'g');
281 0 : snprintf(temp_buf, field_size + 1, szPrintfFormat, dblValue);
282 0 : break;
283 :
284 0 : case 'e':
285 : case 'E':
286 : /* Double precision floating point data type (forced exponent) */
287 0 : snprintf(szPrintfFormat, sizeof(szPrintfFormat), "%%%s%c",
288 : format + 1, 'e');
289 0 : snprintf(temp_buf, field_size + 1, szPrintfFormat, dblValue);
290 0 : break;
291 :
292 0 : case 'a':
293 : case 'A':
294 : #if 0
295 : strncpy(temp_buf,value,field_size+1);
296 : temp_buf[field_size] = '0';
297 : break;
298 : #endif
299 0 : fprintf(stderr, "SetCeosField with format=%c not implemented",
300 0 : format[0]);
301 0 : HFree(temp_buf);
302 0 : return;
303 :
304 0 : default:
305 : /* Unknown format */
306 0 : HFree(temp_buf);
307 0 : return;
308 : }
309 :
310 0 : memcpy(record->Buffer + start_byte - 1, temp_buf, field_size);
311 :
312 0 : HFree(temp_buf);
313 : }
314 :
315 0 : void SetIntCeosField(CeosRecord_t *record, int32 start_byte, int32 length,
316 : int32 value)
317 : {
318 0 : int integer_value = value;
319 : char total_len[12]; /* 12 because 2^32 -> 4294967296 + I + null */
320 :
321 0 : snprintf(total_len, sizeof(total_len), "I%d", length);
322 0 : SetCeosField(record, start_byte, total_len, integer_value, 0.0);
323 0 : }
324 :
325 272 : CeosRecord_t *FindCeosRecord(Link_t *record_list, CeosTypeCode_t typecode,
326 : int32 fileid, int32 flavor, int32 subsequence)
327 : {
328 : Link_t *Link;
329 : CeosRecord_t *record;
330 :
331 3422 : for (Link = record_list; Link != NULL; Link = Link->next)
332 : {
333 3274 : record = (CeosRecord_t *)Link->object;
334 :
335 3274 : if ((record->TypeCode.Int32Code == typecode.Int32Code) &&
336 160 : ((fileid == -1) || (record->FileId == fileid)) &&
337 124 : ((flavor == -1) || (record->Flavor == flavor)) &&
338 0 : ((subsequence == -1) || (record->Subsequence == subsequence)))
339 124 : return record;
340 : }
341 :
342 148 : return NULL;
343 : }
344 :
345 0 : CPL_INLINE static void CPL_IGNORE_RET_VAL_SIZET(CPL_UNUSED size_t unused)
346 : {
347 0 : }
348 :
349 0 : void SerializeCeosRecordsToFile(Link_t *record_list, VSILFILE *fp)
350 : {
351 : Link_t *list;
352 : CeosRecord_t crec;
353 : unsigned char *Buffer;
354 :
355 0 : list = record_list;
356 :
357 0 : while (list != NULL)
358 : {
359 0 : memcpy(&crec, list->object, sizeof(CeosRecord_t));
360 0 : Buffer = crec.Buffer;
361 0 : crec.Buffer = NULL;
362 0 : CPL_IGNORE_RET_VAL_SIZET(
363 : VSIFWriteL(&crec, sizeof(CeosRecord_t), 1, fp));
364 0 : CPL_IGNORE_RET_VAL_SIZET(VSIFWriteL(Buffer, crec.Length, 1, fp));
365 : }
366 0 : }
367 :
368 0 : void SerializeCeosRecordsFromFile(Link_t *record_list, VSILFILE *fp)
369 : {
370 : CeosRecord_t *crec;
371 : Link_t *Link;
372 :
373 0 : while (!VSIFEofL(fp))
374 : {
375 0 : crec = HMalloc(sizeof(CeosRecord_t));
376 0 : CPL_IGNORE_RET_VAL_SIZET(VSIFReadL(crec, sizeof(CeosRecord_t), 1, fp));
377 0 : crec->Buffer = HMalloc(crec->Length * sizeof(char));
378 0 : CPL_IGNORE_RET_VAL_SIZET(
379 0 : VSIFReadL(crec->Buffer, sizeof(char), crec->Length, fp));
380 0 : Link = ceos2CreateLink(crec);
381 0 : AddLink(record_list, Link);
382 : }
383 0 : }
384 :
385 0 : void CeosUpdateHeaderFromBuffer(CeosRecord_t *record)
386 : {
387 0 : if (record && record->Buffer)
388 : {
389 0 : CeosToNative(&(record->Length), record->Buffer + LENGTH_OFF,
390 : sizeof(record->Length), sizeof(record->Length));
391 0 : memcpy(&(record->TypeCode.Int32Code), record->Buffer + TYPE_OFF,
392 : sizeof(record->TypeCode.Int32Code));
393 0 : CeosToNative(&(record->Sequence), record->Buffer + SEQUENCE_OFF,
394 : sizeof(record->Sequence), sizeof(record->Sequence));
395 : }
396 0 : if (record)
397 0 : record->Subsequence = 0;
398 0 : }
399 :
400 : #ifdef CPL_LSB
401 :
402 430 : static void swapbyte(void *dst, void *src, size_t toswap)
403 : {
404 : size_t i, e;
405 430 : unsigned char *in = (unsigned char *)src;
406 430 : unsigned char *out = (unsigned char *)dst;
407 :
408 2150 : for (i = 0, e = toswap; i < toswap; i++, e--)
409 : {
410 1720 : out[i] = in[e - 1];
411 : }
412 430 : }
413 :
414 430 : void NativeToCeos(void *dst, const void *src, const size_t len,
415 : const size_t swapunit)
416 : {
417 : size_t i;
418 : size_t l_remainder;
419 : size_t units;
420 :
421 430 : l_remainder = len % swapunit;
422 :
423 430 : units = len - l_remainder;
424 :
425 860 : for (i = 0; i < units; i += swapunit)
426 : {
427 430 : swapbyte((unsigned char *)dst + i, (unsigned char *)src + i, swapunit);
428 : }
429 :
430 430 : if (l_remainder)
431 : {
432 0 : memcpy((unsigned char *)dst + i, (unsigned char *)src + i, l_remainder);
433 : }
434 430 : }
435 :
436 : #endif
|