Coverage Report

Created: 2026-08-14 09:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/frmts/ceos2/ceos.c
Line
Count
Source
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
void InitEmptyCeosRecord(CeosRecord_t *record, int32 sequence,
23
                         CeosTypeCode_t typecode, int32 length)
24
0
{
25
0
    if (record)
26
0
    {
27
0
        if ((record->Buffer = HMalloc(length)) == NULL)
28
0
        {
29
0
            return;
30
0
        }
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
0
                     sizeof(record->Sequence), sizeof(record->Sequence));
45
0
        memcpy(record->Buffer + TYPE_OFF, &(record->TypeCode.Int32Code),
46
0
               sizeof(record->TypeCode.Int32Code));
47
0
        NativeToCeos(record->Buffer + LENGTH_OFF, &length, sizeof(length),
48
0
                     sizeof(length));
49
0
    }
50
0
}
51
52
void InitCeosRecord(CeosRecord_t *record, uchar *buffer)
53
0
{
54
0
    if (record && buffer)
55
0
    {
56
0
        InitCeosRecordWithHeader(record, buffer, buffer + CEOS_HEADER_LENGTH);
57
0
    }
58
0
}
59
60
void InitCeosRecordWithHeader(CeosRecord_t *record, uchar *header,
61
                              uchar *buffer)
62
424
{
63
424
    if (record && buffer && header)
64
424
    {
65
424
        if (record->Length != 0)
66
424
            record->Length = DetermineCeosRecordBodyLength(header);
67
68
424
        if (record->Length < CEOS_HEADER_LENGTH ||
69
424
            (record->Buffer = HMalloc(record->Length)) == NULL)
70
0
        {
71
0
            record->Length = 0;
72
0
            return;
73
0
        }
74
75
        /* First copy the header then the buffer */
76
424
        memcpy(record->Buffer, header, CEOS_HEADER_LENGTH);
77
        /* Now we copy the rest */
78
424
        if (record->Length > CEOS_HEADER_LENGTH)
79
424
            memcpy(record->Buffer + CEOS_HEADER_LENGTH, buffer,
80
424
                   record->Length - CEOS_HEADER_LENGTH);
81
82
        /* Now we fill in the rest of the structure! */
83
424
        memcpy(&(record->TypeCode.Int32Code), header + TYPE_OFF,
84
424
               sizeof(record->TypeCode.Int32Code));
85
424
        CeosToNative(&(record->Sequence), header + SEQUENCE_OFF,
86
424
                     sizeof(record->Sequence), sizeof(record->Sequence));
87
424
    }
88
424
}
89
90
int DetermineCeosRecordBodyLength(const uchar *header)
91
903
{
92
903
    int i;
93
94
903
    if (header)
95
903
    {
96
903
        CeosToNative(&i, header + LENGTH_OFF, sizeof(i), sizeof(i));
97
903
        return i;
98
903
    }
99
100
0
    return -1;
101
903
}
102
103
void DeleteCeosRecord(CeosRecord_t *record)
104
424
{
105
424
    if (record)
106
424
    {
107
424
        if (record->Buffer)
108
424
        {
109
424
            HFree(record->Buffer);
110
424
            record->Buffer = NULL;
111
424
        }
112
424
        HFree(record);
113
424
    }
114
424
}
115
116
void GetCeosRecordStruct(const CeosRecord_t *record, void *struct_ptr)
117
0
{
118
0
    if (record && struct_ptr && record->Buffer)
119
0
    {
120
0
        memcpy(record->Buffer, struct_ptr, record->Length);
121
0
    }
122
0
}
123
124
void PutCeosRecordStruct(CeosRecord_t *record, const void *struct_ptr)
125
0
{
126
0
    int Length;
127
128
0
    if (record && struct_ptr)
129
0
    {
130
0
        CeosToNative(&Length, struct_ptr, sizeof(Length), sizeof(Length));
131
0
        memcpy(record->Buffer, struct_ptr, Length);
132
0
        CeosUpdateHeaderFromBuffer(record);
133
0
    }
134
0
}
135
136
void GetCeosField(const CeosRecord_t *record, int32 start_byte,
137
                  const char *format, void *value)
138
689
{
139
689
    char *d_ptr;
140
689
    char *mod_buf = NULL;
141
142
689
    const int field_size = atoi(format + 1);
143
689
    assert(field_size >= 1);
144
145
689
    if (format[0] == 'a' || format[0] == 'A')
146
222
    {
147
222
        ((char *)value)[0] = 0;
148
222
        ((char *)value)[field_size] = 0;
149
222
    }
150
151
    /* Check for out of bounds */
152
689
    if (start_byte + field_size - 1 > record->Length)
153
0
    {
154
0
        CPLError(CE_Failure, CPLE_AppDefined,
155
0
                 "Cannot read field. Would require record to be at least %d "
156
0
                 "bytes large, whereas it is only %d",
157
0
                 start_byte + field_size - 1, record->Length);
158
0
        return;
159
0
    }
160
161
689
    if ((mod_buf = (char *)HMalloc(field_size + 1)) == NULL)
162
0
    {
163
0
        return;
164
0
    }
165
166
689
    memcpy(mod_buf, record->Buffer + (start_byte - 1), field_size);
167
689
    mod_buf[field_size] = 0;
168
169
    /* Switch on format type */
170
689
    switch (format[0])
171
689
    {
172
0
        case 'b':
173
183
        case 'B':
174
            /* Binary data type */
175
183
            if (field_size > 1)
176
183
            {
177
183
                CeosToNative(value, mod_buf, field_size, field_size);
178
183
            }
179
0
            else
180
0
            {
181
0
                memcpy(value, mod_buf, field_size);
182
0
            }
183
183
            break;
184
185
0
        case 'i':
186
284
        case 'I':
187
            /* Integer type */
188
284
            *((int *)value) = atoi(mod_buf);
189
284
            break;
190
191
0
        case 'f':
192
0
        case 'F':
193
0
        case 'e':
194
0
        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
0
            {
200
0
                *d_ptr = 'e';
201
0
            }
202
0
            if ((d_ptr = strchr(mod_buf, 'D')) != NULL)
203
0
            {
204
0
                *d_ptr = 'e';
205
0
            }
206
207
0
            *((double *)value) = strtod(mod_buf, NULL);
208
0
            break;
209
0
        case 'a':
210
222
        case 'A':
211
            /* ASCII..  We just easily extract it */
212
222
            ((char *)value)[field_size] = '\0';
213
222
            memcpy(value, mod_buf, field_size);
214
222
            break;
215
216
0
        default:
217
            /* Unknown format.  Do nothing. */
218
0
            break;
219
689
    }
220
221
689
    HFree(mod_buf);
222
689
}
223
224
void SetCeosField(CeosRecord_t *record, int32 start_byte, const char *format,
225
                  int intValue, double dblValue)
226
0
{
227
0
    int field_size;
228
0
    char *temp_buf = NULL;
229
0
    char szPrintfFormat[20];
230
231
0
    field_size = 0;
232
0
    sscanf(&format[1], "%d", &field_size);
233
0
    if (field_size < 1)
234
0
    {
235
0
        return;
236
0
    }
237
238
    /* Check for bounds */
239
0
    if (start_byte + field_size - 1 > record->Length)
240
0
    {
241
0
        return;
242
0
    }
243
244
    /* Make a local buffer to print into */
245
0
    if ((temp_buf = (char *)HMalloc(field_size + 1)) == NULL)
246
0
    {
247
0
        return;
248
0
    }
249
0
    switch (format[0])
250
0
    {
251
0
        case 'b':
252
0
        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
0
        case 'I':
270
            /* Integer data type */
271
0
            snprintf(szPrintfFormat, sizeof(szPrintfFormat), "%%%s%c",
272
0
                     format + 1, 'd');
273
0
            snprintf(temp_buf, field_size + 1, szPrintfFormat, intValue);
274
0
            break;
275
276
0
        case 'f':
277
0
        case 'F':
278
            /* Double precision floating point data type */
279
0
            snprintf(szPrintfFormat, sizeof(szPrintfFormat), "%%%s%c",
280
0
                     format + 1, 'g');
281
0
            snprintf(temp_buf, field_size + 1, szPrintfFormat, dblValue);
282
0
            break;
283
284
0
        case 'e':
285
0
        case 'E':
286
            /* Double precision floating point data type (forced exponent) */
287
0
            snprintf(szPrintfFormat, sizeof(szPrintfFormat), "%%%s%c",
288
0
                     format + 1, 'e');
289
0
            snprintf(temp_buf, field_size + 1, szPrintfFormat, dblValue);
290
0
            break;
291
292
0
        case 'a':
293
0
        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
0
    }
309
310
0
    memcpy(record->Buffer + start_byte - 1, temp_buf, field_size);
311
312
0
    HFree(temp_buf);
313
0
}
314
315
void SetIntCeosField(CeosRecord_t *record, int32 start_byte, int32 length,
316
                     int32 value)
317
0
{
318
0
    int integer_value = value;
319
0
    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
CeosRecord_t *FindCeosRecord(Link_t *record_list, CeosTypeCode_t typecode,
326
                             int32 fileid, int32 flavor, int32 subsequence)
327
1.11k
{
328
1.11k
    Link_t *Link;
329
1.11k
    CeosRecord_t *record;
330
331
19.6k
    for (Link = record_list; Link != NULL; Link = Link->next)
332
19.0k
    {
333
19.0k
        record = (CeosRecord_t *)Link->object;
334
335
19.0k
        if ((record->TypeCode.Int32Code == typecode.Int32Code) &&
336
2.18k
            ((fileid == -1) || (record->FileId == fileid)) &&
337
475
            ((flavor == -1) || (record->Flavor == flavor)) &&
338
475
            ((subsequence == -1) || (record->Subsequence == subsequence)))
339
473
            return record;
340
19.0k
    }
341
342
641
    return NULL;
343
1.11k
}
344
345
CPL_INLINE static void CPL_IGNORE_RET_VAL_SIZET(CPL_UNUSED size_t unused)
346
0
{
347
0
}
348
349
void SerializeCeosRecordsToFile(Link_t *record_list, VSILFILE *fp)
350
0
{
351
0
    Link_t *list;
352
0
    CeosRecord_t crec;
353
0
    unsigned char *Buffer;
354
355
0
    list = record_list;
356
357
0
    while (list != NULL)
358
0
    {
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
0
            VSIFWriteL(&crec, sizeof(CeosRecord_t), 1, fp));
364
0
        CPL_IGNORE_RET_VAL_SIZET(VSIFWriteL(Buffer, crec.Length, 1, fp));
365
0
    }
366
0
}
367
368
void SerializeCeosRecordsFromFile(Link_t *record_list, VSILFILE *fp)
369
0
{
370
0
    CeosRecord_t *crec;
371
0
    Link_t *Link;
372
373
0
    while (!VSIFEofL(fp))
374
0
    {
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
0
    }
383
0
}
384
385
void CeosUpdateHeaderFromBuffer(CeosRecord_t *record)
386
0
{
387
0
    if (record && record->Buffer)
388
0
    {
389
0
        CeosToNative(&(record->Length), record->Buffer + LENGTH_OFF,
390
0
                     sizeof(record->Length), sizeof(record->Length));
391
0
        memcpy(&(record->TypeCode.Int32Code), record->Buffer + TYPE_OFF,
392
0
               sizeof(record->TypeCode.Int32Code));
393
0
        CeosToNative(&(record->Sequence), record->Buffer + SEQUENCE_OFF,
394
0
                     sizeof(record->Sequence), sizeof(record->Sequence));
395
0
    }
396
0
    if (record)
397
0
        record->Subsequence = 0;
398
0
}
399
400
#ifdef CPL_LSB
401
402
static void swapbyte(void *dst, void *src, size_t toswap)
403
1.98k
{
404
1.98k
    size_t i, e;
405
1.98k
    unsigned char *in = (unsigned char *)src;
406
1.98k
    unsigned char *out = (unsigned char *)dst;
407
408
9.94k
    for (i = 0, e = toswap; i < toswap; i++, e--)
409
7.95k
    {
410
7.95k
        out[i] = in[e - 1];
411
7.95k
    }
412
1.98k
}
413
414
void NativeToCeos(void *dst, const void *src, const size_t len,
415
                  const size_t swapunit)
416
1.98k
{
417
1.98k
    size_t i;
418
1.98k
    size_t l_remainder;
419
1.98k
    size_t units;
420
421
1.98k
    l_remainder = len % swapunit;
422
423
1.98k
    units = len - l_remainder;
424
425
3.97k
    for (i = 0; i < units; i += swapunit)
426
1.98k
    {
427
1.98k
        swapbyte((unsigned char *)dst + i, (unsigned char *)src + i, swapunit);
428
1.98k
    }
429
430
1.98k
    if (l_remainder)
431
0
    {
432
0
        memcpy((unsigned char *)dst + i, (unsigned char *)src + i, l_remainder);
433
0
    }
434
1.98k
}
435
436
#endif