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