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