Skip to content

Commit 033b287

Browse files
committed
Check datatype match inside segy_set_field
.datatype field is kind of pointless at the moment. - In C we can't easily force someone to set datatype the same moment when .value is set. So nothing prevents us from setting value to i16 and datatype to u32. - In theory we can simply pass segy_field_value as an argument instead of passing full segy_field_data. However it doesn't fit into the spirit of function, as without knowing .datatype we can't interpret value on its own and are forced to do it according to the field mapping table instead of the actual datatype. The best option seems to force .datatype being set by checking that it corresponds to the datatype retrieved from field mapping. Additionally fd doesn't have to be a pointer. We should treat that value as any other local primitive as it is not that big in size.
1 parent b9e3f3d commit 033b287

5 files changed

Lines changed: 46 additions & 24 deletions

File tree

lib/include/segyio/segy.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ int segy_set_endianness( segy_datasource*, int opt );
198198
int segy_field_datatype( int field );
199199

200200
int segy_get_field( const char* header, int field, segy_field_data* fd );
201-
int segy_set_field( char* header, int field, segy_field_data* fd );
201+
int segy_set_field( char* header, int field, segy_field_data fd );
202202

203203
int segy_get_field_int( const char* header, int field, int* f );
204204
int segy_set_field_int( char* header, const int field, const int val );

lib/src/segy.c

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -920,59 +920,65 @@ int segy_get_field_int( const char* header, int field, int* val ) {
920920
return fd_get_int( &fd, val );
921921
}
922922

923-
int segy_set_field( char* header, int field, segy_field_data* fd ) {
923+
int segy_set_field( char* header, int field, segy_field_data fd ) {
924924
int offset = field - 1;
925925
if (offset >= SEGY_TEXT_HEADER_SIZE) {
926926
offset -= SEGY_TEXT_HEADER_SIZE;
927927
}
928928

929-
segy_field_value fv = fd->value;
929+
segy_field_value fv = fd.value;
930930
uint64_t val;
931-
switch ( fd->datatype ) {
931+
932+
uint8_t datatype = segy_field_datatype( field );
933+
if (fd.datatype != datatype) {
934+
return SEGY_INVALID_FIELD_DATATYPE;
935+
}
936+
937+
switch ( fd.datatype ) {
932938

933939
case SEGY_SIGNED_INTEGER_8_BYTE:
934940
fv.i64 = htobe64( fv.i64 );
935-
memcpy( header + offset, &(fv.i64), formatsize( fd->datatype ));
941+
memcpy( header + offset, &(fv.i64), formatsize( fd.datatype ));
936942
return SEGY_OK;
937943

938944
case SEGY_SIGNED_INTEGER_4_BYTE:
939945
fv.i32 = htobe32( fv.i32 );
940-
memcpy( header + offset, &(fv.i32), formatsize( fd->datatype ));
946+
memcpy( header + offset, &(fv.i32), formatsize( fd.datatype ));
941947
return SEGY_OK;
942948

943949
case SEGY_SIGNED_SHORT_2_BYTE:
944950
fv.i16 = htobe16( fv.i16 );
945-
memcpy( header + offset, &(fv.i16), formatsize( fd->datatype ));
951+
memcpy( header + offset, &(fv.i16), formatsize( fd.datatype ));
946952
return SEGY_OK;
947953

948954
case SEGY_SIGNED_CHAR_1_BYTE:
949-
memcpy( header + offset, &(fv.i8), formatsize( fd->datatype ));
955+
memcpy( header + offset, &(fv.i8), formatsize( fd.datatype ));
950956
return SEGY_OK;
951957

952958
case SEGY_UNSIGNED_INTEGER_8_BYTE:
953959
fv.u64 = htobe64( fv.u64 );
954-
memcpy( header + offset, &(fv.u64), formatsize( fd->datatype ));
960+
memcpy( header + offset, &(fv.u64), formatsize( fd.datatype ));
955961
return SEGY_OK;
956962

957963
case SEGY_UNSIGNED_INTEGER_4_BYTE:
958964
fv.u32 = htobe32( fv.u32 );
959-
memcpy( header + offset, &(fv.u32), formatsize( fd->datatype ));
965+
memcpy( header + offset, &(fv.u32), formatsize( fd.datatype ));
960966
return SEGY_OK;
961967

962968
case SEGY_UNSIGNED_SHORT_2_BYTE:
963969
fv.u16 = htobe16( fv.u16 );
964-
memcpy( header + offset, &(fv.u16), formatsize( fd->datatype ));
970+
memcpy( header + offset, &(fv.u16), formatsize( fd.datatype ));
965971
return SEGY_OK;
966972

967973
case SEGY_UNSIGNED_CHAR_1_BYTE:
968-
memcpy( header + offset, &(fv.u8), formatsize( fd->datatype ));
974+
memcpy( header + offset, &(fv.u8), formatsize( fd.datatype ));
969975
return SEGY_OK;
970976

971977
case SEGY_IEEE_FLOAT_8_BYTE:
972978
memcpy( &val, &(fv.f64), sizeof( uint64_t ) );
973979
val = htobe64( val );
974980
memcpy( &(fv.f64), &val, sizeof( uint64_t ) );
975-
memcpy( header + offset, &(fv.f64), formatsize( fd->datatype ));
981+
memcpy( header + offset, &(fv.f64), formatsize( fd.datatype ));
976982
return SEGY_OK;
977983

978984
default:
@@ -1023,7 +1029,7 @@ int segy_set_field_int( char* header, const int field, const int val ) {
10231029
int err = fd_set_int( &fd, val );
10241030
if( err != SEGY_OK ) return err;
10251031

1026-
return segy_set_field( header, field, &fd );
1032+
return segy_set_field( header, field, fd );
10271033
}
10281034

10291035
static int slicelength( int start, int stop, int step ) {

lib/src/segy.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ segy_sample_interval
1212
segy_format
1313
segy_set_format
1414
segy_set_endianness
15+
segy_get_field
16+
segy_set_field
1517
segy_get_field_int
1618
segy_set_field_int
1719
segy_field_forall

lib/test/segy.cpp

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,11 @@ struct Err {
6969
bool operator == ( Err other ) const { return this->err == other.err; }
7070
bool operator != ( Err other ) const { return !(*this == other); }
7171

72-
static Err ok() { return SEGY_OK; }
73-
static Err args() { return SEGY_INVALID_ARGS; }
74-
static Err field() { return SEGY_INVALID_FIELD; }
75-
static Err value() { return SEGY_INVALID_FIELD_VALUE; }
72+
static Err ok() { return SEGY_OK; }
73+
static Err args() { return SEGY_INVALID_ARGS; }
74+
static Err field() { return SEGY_INVALID_FIELD; }
75+
static Err value() { return SEGY_INVALID_FIELD_VALUE; }
76+
static Err datatype() { return SEGY_INVALID_FIELD_DATATYPE; }
7677

7778
int err;
7879
};
@@ -2053,10 +2054,11 @@ TEST_CASE("segy_get_field reads values correctly", "[c.segy]" ) {
20532054
header[SEGY_TR_TRACE_ID-1] = b1;
20542055
header[SEGY_TR_TRACE_ID-0] = b0;
20552056

2056-
int read_value;
2057-
Err err = segy_get_field_int( header, SEGY_TR_TRACE_ID, &read_value );
2057+
segy_field_data read_value;
2058+
Err err = segy_get_field( header, SEGY_TR_TRACE_ID, &read_value );
20582059
CHECK( success( err ) );
2059-
CHECK( read_value == value );
2060+
CHECK( read_value.datatype == SEGY_SIGNED_SHORT_2_BYTE );
2061+
CHECK( read_value.value.i16 == value );
20602062
}
20612063
}
20622064

@@ -2066,7 +2068,11 @@ TEST_CASE("segy_set_field write values correctly", "[c.segy]" ) {
20662068

20672069
SECTION("test edge cases int16") {
20682070
int16_t value = GENERATE(0, 1, -1, 0x0102, 0x0201, -32767, -32766);
2069-
Err err = segy_set_field_int( header, SEGY_TR_TRACE_ID, value );
2071+
2072+
segy_field_data fd;
2073+
fd.datatype = SEGY_SIGNED_SHORT_2_BYTE;
2074+
fd.value.i16 = value;
2075+
Err err = segy_set_field( header, SEGY_TR_TRACE_ID, fd );
20702076
CHECK( err == Err::ok() );
20712077

20722078
uint8_t b0 = header[SEGY_TR_TRACE_ID-0];
@@ -2080,9 +2086,17 @@ TEST_CASE("segy_set_field write invalid value", "[c.segy]" ) {
20802086

20812087
char header[ SEGY_TRACE_HEADER_SIZE ] = { 0 };
20822088

2083-
SECTION("test value outside of int16 range") {
2089+
SECTION("test value outside of int16 range for segy_set_field_int") {
20842090
int32_t value = 0xFFFF + 1;
20852091
Err err = segy_set_field_int( header, SEGY_TR_TRACE_ID, value );
20862092
CHECK( err == Err::value() );
20872093
}
2094+
2095+
SECTION("test mismatched type") {
2096+
segy_field_data fd;
2097+
fd.value.i16 = 42;
2098+
fd.datatype = SEGY_SIGNED_INTEGER_4_BYTE;
2099+
Err err = segy_set_field( header, SEGY_TR_TRACE_ID, fd );
2100+
CHECK( err == Err::datatype() );
2101+
}
20882102
}

python/segyio/segyio.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1846,7 +1846,7 @@ PyObject* putfield( PyObject*, PyObject *args ) {
18461846
return KeyError( "Field %d has unknown datatype %d", field, fd.datatype );
18471847
}
18481848

1849-
int err = segy_set_field( buffer.buf< char >(), field, &fd );
1849+
int err = segy_set_field( buffer.buf< char >(), field, fd );
18501850

18511851
switch( err ) {
18521852
case SEGY_OK:

0 commit comments

Comments
 (0)