gdal/frmts/ceos2/ceos.c

446 строки
12 KiB
C

/******************************************************************************
* $Id$
*
* Project: ASI CEOS Translator
* Purpose: Core CEOS functions.
* Author: Paul Lahaie, pjlahaie@atlsci.com
*
******************************************************************************
* Copyright (c) 2000, Atlantis Scientific Inc
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
****************************************************************************/
#include "ceos.h"
/* Function implementations of functions described in ceos.h */
void CeosUpdateHeaderFromBuffer(CeosRecord_t *record);
void InitEmptyCeosRecord(CeosRecord_t *record, int32 sequence,
CeosTypeCode_t typecode, int32 length)
{
if (record)
{
if ((record->Buffer = HMalloc(length)) == NULL)
{
return;
}
/* First we zero fill the buffer */
memset(record->Buffer, 0, length);
/* Setup values inside the CeosRecord_t header */
record->Sequence = sequence;
record->Flavor = 0;
record->FileId = 0;
record->TypeCode = typecode;
record->Subsequence = 0;
record->Length = length;
/* Now we fill in the buffer portion as well */
NativeToCeos(record->Buffer + SEQUENCE_OFF, &(record->Sequence),
sizeof(record->Sequence), sizeof(record->Sequence));
memcpy(record->Buffer + TYPE_OFF, &(record->TypeCode.Int32Code),
sizeof(record->TypeCode.Int32Code));
NativeToCeos(record->Buffer + LENGTH_OFF, &length, sizeof(length),
sizeof(length));
}
}
void InitCeosRecord(CeosRecord_t *record, uchar *buffer)
{
if (record && buffer)
{
InitCeosRecordWithHeader(record, buffer, buffer + CEOS_HEADER_LENGTH);
}
}
void InitCeosRecordWithHeader(CeosRecord_t *record, uchar *header,
uchar *buffer)
{
if (record && buffer && header)
{
if (record->Length != 0)
record->Length = DetermineCeosRecordBodyLength(header);
if (record->Length < CEOS_HEADER_LENGTH ||
(record->Buffer = HMalloc(record->Length)) == NULL)
{
record->Length = 0;
return;
}
/* First copy the header then the buffer */
memcpy(record->Buffer, header, CEOS_HEADER_LENGTH);
/* Now we copy the rest */
if (record->Length > CEOS_HEADER_LENGTH)
memcpy(record->Buffer + CEOS_HEADER_LENGTH, buffer,
record->Length - CEOS_HEADER_LENGTH);
/* Now we fill in the rest of the structure! */
memcpy(&(record->TypeCode.Int32Code), header + TYPE_OFF,
sizeof(record->TypeCode.Int32Code));
CeosToNative(&(record->Sequence), header + SEQUENCE_OFF,
sizeof(record->Sequence), sizeof(record->Sequence));
}
}
int DetermineCeosRecordBodyLength(const uchar *header)
{
int i;
if (header)
{
CeosToNative(&i, header + LENGTH_OFF, sizeof(i), sizeof(i));
return i;
}
return -1;
}
void DeleteCeosRecord(CeosRecord_t *record)
{
if (record)
{
if (record->Buffer)
{
HFree(record->Buffer);
record->Buffer = NULL;
}
HFree(record);
}
}
void GetCeosRecordStruct(const CeosRecord_t *record, void *struct_ptr)
{
if (record && struct_ptr && record->Buffer)
{
memcpy(record->Buffer, struct_ptr, record->Length);
}
}
void PutCeosRecordStruct(CeosRecord_t *record, const void *struct_ptr)
{
int Length;
if (record && struct_ptr)
{
CeosToNative(&Length, struct_ptr, sizeof(Length), sizeof(Length));
memcpy(record->Buffer, struct_ptr, Length);
CeosUpdateHeaderFromBuffer(record);
}
}
void GetCeosField(CeosRecord_t *record, int32 start_byte, const char *format,
void *value)
{
int field_size;
char *d_ptr;
char *mod_buf = NULL;
field_size = atoi(format + 1);
if (field_size < 1)
{
return;
}
/* Check for out of bounds */
if (start_byte + field_size - 1 > record->Length)
{
return;
}
if ((mod_buf = (char *)HMalloc(field_size + 1)) == NULL)
{
return;
}
memcpy(mod_buf, record->Buffer + (start_byte - 1), field_size);
mod_buf[field_size] = '\0';
/* Switch on format type */
switch (format[0])
{
case 'b':
case 'B':
/* Binary data type */
if (field_size > 1)
{
CeosToNative(value, mod_buf, field_size, field_size);
}
else
{
memcpy(value, mod_buf, field_size);
}
break;
case 'i':
case 'I':
/* Integer type */
*((int *)value) = atoi(mod_buf);
break;
case 'f':
case 'F':
case 'e':
case 'E':
/* Double precision float data type */
/* Change the 'D' exponent separators to 'e' */
if ((d_ptr = strchr(mod_buf, 'd')) != NULL)
{
*d_ptr = 'e';
}
if ((d_ptr = strchr(mod_buf, 'D')) != NULL)
{
*d_ptr = 'e';
}
*((double *)value) = strtod(mod_buf, NULL);
break;
case 'a':
case 'A':
/* ASCII.. We just easily extract it */
((char *)value)[field_size] = '\0';
memcpy(value, mod_buf, field_size);
break;
default:
/* Unknown format. Do nothing. */
break;
}
HFree(mod_buf);
}
void SetCeosField(CeosRecord_t *record, int32 start_byte, const char *format,
int intValue, double dblValue)
{
int field_size;
char *temp_buf = NULL;
char szPrintfFormat[20];
field_size = 0;
sscanf(&format[1], "%d", &field_size);
if (field_size < 1)
{
return;
}
/* Check for bounds */
if (start_byte + field_size - 1 > record->Length)
{
return;
}
/* Make a local buffer to print into */
if ((temp_buf = (char *)HMalloc(field_size + 1)) == NULL)
{
return;
}
switch (format[0])
{
case 'b':
case 'B':
#if 0
/* Binary data type */
if(field_size > 1)
{
NativeToCeos( value, temp_buf, field_size, field_size );
} else {
memcpy(value,temp_buf,field_size);
}
break;
#endif
fprintf(stderr, "SetCeosField with format=%c not implemented",
format[0]);
HFree(temp_buf);
return;
case 'i':
case 'I':
/* Integer data type */
snprintf(szPrintfFormat, sizeof(szPrintfFormat), "%%%s%c",
format + 1, 'd');
snprintf(temp_buf, field_size + 1, szPrintfFormat, intValue);
break;
case 'f':
case 'F':
/* Double precision floating point data type */
snprintf(szPrintfFormat, sizeof(szPrintfFormat), "%%%s%c",
format + 1, 'g');
snprintf(temp_buf, field_size + 1, szPrintfFormat, dblValue);
break;
case 'e':
case 'E':
/* Double precision floating point data type (forced exponent) */
snprintf(szPrintfFormat, sizeof(szPrintfFormat), "%%%s%c",
format + 1, 'e');
snprintf(temp_buf, field_size + 1, szPrintfFormat, dblValue);
break;
case 'a':
case 'A':
#if 0
strncpy(temp_buf,value,field_size+1);
temp_buf[field_size] = '0';
break;
#endif
fprintf(stderr, "SetCeosField with format=%c not implemented",
format[0]);
HFree(temp_buf);
return;
default:
/* Unknown format */
HFree(temp_buf);
return;
}
memcpy(record->Buffer + start_byte - 1, temp_buf, field_size);
HFree(temp_buf);
}
void SetIntCeosField(CeosRecord_t *record, int32 start_byte, int32 length,
int32 value)
{
int integer_value = value;
char total_len[12]; /* 12 because 2^32 -> 4294967296 + I + null */
snprintf(total_len, sizeof(total_len), "I%d", length);
SetCeosField(record, start_byte, total_len, integer_value, 0.0);
}
CeosRecord_t *FindCeosRecord(Link_t *record_list, CeosTypeCode_t typecode,
int32 fileid, int32 flavor, int32 subsequence)
{
Link_t *Link;
CeosRecord_t *record;
for (Link = record_list; Link != NULL; Link = Link->next)
{
record = (CeosRecord_t *)Link->object;
if ((record->TypeCode.Int32Code == typecode.Int32Code) &&
((fileid == -1) || (record->FileId == fileid)) &&
((flavor == -1) || (record->Flavor == flavor)) &&
((subsequence == -1) || (record->Subsequence == subsequence)))
return record;
}
return NULL;
}
CPL_INLINE static void CPL_IGNORE_RET_VAL_SIZET(CPL_UNUSED size_t unused)
{
}
void SerializeCeosRecordsToFile(Link_t *record_list, VSILFILE *fp)
{
Link_t *list;
CeosRecord_t crec;
unsigned char *Buffer;
list = record_list;
while (list != NULL)
{
memcpy(&crec, list->object, sizeof(CeosRecord_t));
Buffer = crec.Buffer;
crec.Buffer = NULL;
CPL_IGNORE_RET_VAL_SIZET(
VSIFWriteL(&crec, sizeof(CeosRecord_t), 1, fp));
CPL_IGNORE_RET_VAL_SIZET(VSIFWriteL(Buffer, crec.Length, 1, fp));
}
}
void SerializeCeosRecordsFromFile(Link_t *record_list, VSILFILE *fp)
{
CeosRecord_t *crec;
Link_t *Link;
while (!VSIFEofL(fp))
{
crec = HMalloc(sizeof(CeosRecord_t));
CPL_IGNORE_RET_VAL_SIZET(VSIFReadL(crec, sizeof(CeosRecord_t), 1, fp));
crec->Buffer = HMalloc(crec->Length * sizeof(char));
CPL_IGNORE_RET_VAL_SIZET(
VSIFReadL(crec->Buffer, sizeof(char), crec->Length, fp));
Link = ceos2CreateLink(crec);
AddLink(record_list, Link);
}
}
void CeosUpdateHeaderFromBuffer(CeosRecord_t *record)
{
if (record && record->Buffer)
{
CeosToNative(&(record->Length), record->Buffer + LENGTH_OFF,
sizeof(record->Length), sizeof(record->Length));
memcpy(&(record->TypeCode.Int32Code), record->Buffer + TYPE_OFF,
sizeof(record->TypeCode.Int32Code));
CeosToNative(&(record->Sequence), record->Buffer + SEQUENCE_OFF,
sizeof(record->Sequence), sizeof(record->Sequence));
}
if (record)
record->Subsequence = 0;
}
#ifdef CPL_LSB
static void swapbyte(void *dst, void *src, size_t toswap)
{
size_t i, e;
unsigned char *in = (unsigned char *)src;
unsigned char *out = (unsigned char *)dst;
for (i = 0, e = toswap; i < toswap; i++, e--)
{
out[i] = in[e - 1];
}
}
void NativeToCeos(void *dst, const void *src, const size_t len,
const size_t swapunit)
{
size_t i;
size_t l_remainder;
size_t units;
l_remainder = len % swapunit;
units = len - l_remainder;
for (i = 0; i < units; i += swapunit)
{
swapbyte((unsigned char *)dst + i, (unsigned char *)src + i, swapunit);
}
if (l_remainder)
{
memcpy((unsigned char *)dst + i, (unsigned char *)src + i, l_remainder);
}
}
#endif