LCOV - code coverage report
Current view: top level - frmts/ceos2 - ceos.c (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 68 187 36.4 %
Date: 2026-03-26 23:25:44 Functions: 7 17 41.2 %

          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

Generated by: LCOV version 1.14