diff --git a/.github/workflows/wheels.yaml b/.github/workflows/wheels.yaml index ae943f21..53467a39 100644 --- a/.github/workflows/wheels.yaml +++ b/.github/workflows/wheels.yaml @@ -54,7 +54,7 @@ jobs: CIBW_ENVIRONMENT_WINDOWS: > CMAKE_GENERATOR="${{ matrix.cmake_generator }}" CMAKE_GENERATOR_PLATFORM="${{ matrix.cmake_generator_platform }}" - CIBW_SKIP: pp* *-musllinux_* cp36-* cp37-* cp38-* + CIBW_SKIP: pp* *-musllinux_* cp36-* cp37-* cp38-* cp314* CIBW_ARCHS: ${{ matrix.arch }} run: | python -m cibuildwheel --output-dir wheelhouse python/ diff --git a/applications/segyinfo.c b/applications/segyinfo.c index 360aa4c1..538842a1 100644 --- a/applications/segyinfo.c +++ b/applications/segyinfo.c @@ -8,10 +8,10 @@ static void printSegyTraceInfo( const char* buf ) { int cdp, tsf, xl, il; - segy_get_field_i32( buf, SEGY_TR_ENSEMBLE, &cdp ); - segy_get_field_i32( buf, SEGY_TR_SEQ_FILE, &tsf ); - segy_get_field_i32( buf, SEGY_TR_CROSSLINE, &xl ); - segy_get_field_i32( buf, SEGY_TR_INLINE, &il ); + segy_get_field_int( buf, SEGY_TR_ENSEMBLE, &cdp ); + segy_get_field_int( buf, SEGY_TR_SEQ_FILE, &tsf ); + segy_get_field_int( buf, SEGY_TR_CROSSLINE, &xl ); + segy_get_field_int( buf, SEGY_TR_INLINE, &il ); printf("cdp: %d\n", cdp ); printf("TraceSequenceFile: %d\n", tsf ); @@ -55,8 +55,8 @@ int main(int argc, char* argv[]) { const int samples = segy_samples( header ); const long trace0 = segy_trace0( header ); const int trace_bsize = segy_trace_bsize( samples ); - int16_t extended_headers; - err = segy_get_field_i16( header, SEGY_BIN_EXT_HEADERS, &extended_headers ); + int extended_headers; + err = segy_get_field_int( header, SEGY_BIN_EXT_HEADERS, &extended_headers ); if( err != 0 ) { perror( "Can't read 'extended headers' field from binary header" ); @@ -113,8 +113,8 @@ int main(int argc, char* argv[]) { exit( err ); } - int16_t sample_count; - err = segy_get_field_i16( traceh, SEGY_TR_SAMPLE_COUNT, &sample_count ); + int sample_count; + err = segy_get_field_int( traceh, SEGY_TR_SAMPLE_COUNT, &sample_count ); if( err != 0 ) { fprintf( stderr, "Invalid trace header field: %d\n", SEGY_TR_SAMPLE_COUNT ); diff --git a/applications/segyio-catb.c b/applications/segyio-catb.c index 2f477e2a..8c38a908 100644 --- a/applications/segyio-catb.c +++ b/applications/segyio-catb.c @@ -77,6 +77,14 @@ typedef struct { const char* description; } binary_field_type; +static void u64_to_buf(char *buf, size_t buflen, unsigned long long int value) { + snprintf(buf, buflen, "%llu", value); +} + +static void i64_to_buf(char *buf, size_t buflen, long long int value) { + snprintf(buf, buflen, "%lld", value); +} + int main( int argc, char** argv ){ if( argc == 1 ){ @@ -151,39 +159,51 @@ int main( int argc, char** argv ){ int nr_fields = sizeof(field_data)/sizeof(binary_field_type); for( int c = 0; c < nr_fields; ++c ){ - segy_field_data fd = segy_get_field( binheader, field_data[c].offset ); - if ( fd.error ) return errmsg( fd.error, "Unable to read field" ); - - int byte_offset = (field_data[c].offset - SEGY_TEXT_HEADER_SIZE); - const char* short_name = field_data[c].short_name; - const char* description = field_data[c].description; - - if( fd.datatype == SEGY_UNSIGNED_INTEGER_8_BYTE ) { - unsigned long long int field = fd.value.u64; - if( opts.nonzero && field == 0) continue; - if( opts.description ) - printf( "%s\t%llu\t%d\t%s\n", short_name, field, byte_offset, description ); - else - printf( "%-10s\t%llu\n", short_name, field ); + segy_field_data fd; + err = segy_get_field( binheader, field_data[c].offset, &fd ); + if ( err ) return errmsg( err, "Unable to read field" ); + + bool value_is_zero = false; + char value_str[40]; // should be enough for all strings + + switch( fd.datatype ) { + case SEGY_UNSIGNED_INTEGER_8_BYTE: { + u64_to_buf( value_str, sizeof( value_str ), fd.value.u64 ); + } break; + case SEGY_UNSIGNED_SHORT_2_BYTE: { + u64_to_buf( value_str, sizeof( value_str ), fd.value.u16 ); + } break; + case SEGY_UNSIGNED_CHAR_1_BYTE: { + u64_to_buf( value_str, sizeof( value_str ), fd.value.u8 ); + } break; + case SEGY_SIGNED_INTEGER_4_BYTE: { + i64_to_buf( value_str, sizeof( value_str ), fd.value.i32 ); + } break; + case SEGY_SIGNED_SHORT_2_BYTE: { + i64_to_buf( value_str, sizeof( value_str ), fd.value.i16 ); + } break; + case SEGY_IEEE_FLOAT_8_BYTE: { + double value = fd.value.f64; + value_is_zero = (value == 0.0); + snprintf( value_str, sizeof( value_str ), "%f", value ); + } break; + default: { + return errmsg( -1, "Unhandled field format" ); + } } - else if( fd.datatype == SEGY_IEEE_FLOAT_8_BYTE ) { - double field = fd.value.f64; - if( opts.nonzero && field == 0.0) continue; - if( opts.description ) - printf( "%s\t%f\t%d\t%s\n", short_name, field, byte_offset, description ); - else - printf( "%-10s\t%f\n", short_name, field ); + + if (strcmp( value_str, "0" ) == 0) { + value_is_zero = true; } - else { - int field; - err = segy_field_data_to_int( &fd, &field ); - if( err ) return errmsg( err, "Unable to convert segy_field_data to int32" ); - - if( opts.nonzero && field == 0) continue; - if( opts.description ) - printf( "%s\t%d\t%d\t%s\n", short_name, field, byte_offset, description ); - else - printf( "%-10s\t%d\n", short_name, field ); + + if( opts.nonzero && value_is_zero ) continue; + if( opts.description ) { + int byte_offset = (field_data[c].offset - SEGY_TEXT_HEADER_SIZE); + const char* short_name = field_data[c].short_name; + const char* description = field_data[c].description; + printf( "%s\t%s\t%d\t%s\n", short_name, value_str, byte_offset, description ); + } else { + printf( "%-10s\t%s\n", field_data[c].short_name, value_str ); } } segy_close( fp ); diff --git a/applications/segyio-cath.c b/applications/segyio-cath.c index fa1cc2c6..b2bf7cce 100644 --- a/applications/segyio-cath.c +++ b/applications/segyio-cath.c @@ -34,8 +34,8 @@ static int ext_headers( segy_file* fp ) { if( err ) return -1; - int16_t ext; - err = segy_get_field_i16( binary, SEGY_BIN_EXT_HEADERS, &ext ); + int ext; + err = segy_get_field_int( binary, SEGY_BIN_EXT_HEADERS, &ext ); if( err ) return -2; return ext; } diff --git a/applications/segyio-crop.c b/applications/segyio-crop.c index 0e2d798d..13357e40 100644 --- a/applications/segyio-crop.c +++ b/applications/segyio-crop.c @@ -51,10 +51,10 @@ static struct delay delay_recording_time( const char* trheader, int dt, int samples ) { - int16_t t0; - segy_get_field_i16( trheader, SEGY_TR_DELAY_REC_TIME, &t0 ); - int16_t trdt; - segy_get_field_i16( trheader, SEGY_TR_SAMPLE_INTER, &trdt ); + int t0; + segy_get_field_int( trheader, SEGY_TR_DELAY_REC_TIME, &t0 ); + int trdt; + segy_get_field_int( trheader, SEGY_TR_SAMPLE_INTER, &trdt ); if( trdt ) dt = trdt; /* @@ -408,8 +408,8 @@ int main( int argc, char** argv ) { if( sz != 1 ) exit( errmsg2( errno, "Unable to write binary header", strerror( errno ) ) ); - int16_t ext_headers; - int err = segy_get_field_i16(binheader, SEGY_BIN_EXT_HEADERS, &ext_headers); + int ext_headers; + int err = segy_get_field_int(binheader, SEGY_BIN_EXT_HEADERS, &ext_headers); if( err != SEGY_OK ) exit( errmsg( -1, "Malformed binary header" ) ); for( int i = 0; i < ext_headers; ++i ) { @@ -424,10 +424,10 @@ int main( int argc, char** argv ) { } if( verbosity > 2 ) puts( "Computing samples-per-trace" ); - int16_t bindt; - segy_get_field_i16( binheader, SEGY_BIN_INTERVAL, &bindt ); - uint16_t src_samples; - err = segy_get_field_u16( binheader, SEGY_BIN_SAMPLES, &src_samples ); + int bindt; + segy_get_field_int( binheader, SEGY_BIN_INTERVAL, &bindt ); + int src_samples; + err = segy_get_field_int( binheader, SEGY_BIN_SAMPLES, &src_samples ); if( err != SEGY_OK ) exit( errmsg( -2, "Could not determine samples per trace" ) ); @@ -514,9 +514,9 @@ int main( int argc, char** argv ) { bindt, src_samples ); - segy_set_field_u16( trheader, SEGY_TR_SAMPLE_COUNT, d.len ); - segy_set_field_i16( trheader, SEGY_TR_DELAY_REC_TIME, d.delay ); - segy_set_field_u16( binheader, SEGY_BIN_SAMPLES, d.len ); + segy_set_field_int( trheader, SEGY_TR_SAMPLE_COUNT, d.len ); + segy_set_field_int( trheader, SEGY_TR_DELAY_REC_TIME, d.delay ); + segy_set_field_int( binheader, SEGY_BIN_SAMPLES, d.len ); if( verbosity > 2 ) printf( "Copying trace %lld\n", traces ); sz = fwrite( trheader, TRHSIZE, 1, dst ); diff --git a/lib/include/segyio/segy.h b/lib/include/segyio/segy.h index 9c06b797..1dcd571b 100644 --- a/lib/include/segyio/segy.h +++ b/lib/include/segyio/segy.h @@ -132,9 +132,6 @@ typedef union { typedef struct { segy_field_value value; uint8_t datatype; - int32_t field_index; - int32_t field_offset; - int32_t error; } segy_field_data; segy_file* segy_open( const char* path, const char* mode ); @@ -194,33 +191,17 @@ int segy_set_format( segy_datasource*, int format ); */ int segy_set_endianness( segy_datasource*, int opt ); -/* Initialize the segy_field_data structure using the field number - * - * If the field number is greater than SEGY_TEXT_HEADER_SIZE [3200] - * the field is assumed to be a binary header field. - * Binary header field: field_index = (field number)-3200, field_offset = 3200 - * Trace header field : field_index = field number, field_offset = 0 - * Tables tr_field_type and bin_field_type are used to set the datatype. +/* Gets field datatype from field id. Depending on field value, binary or trace + * mapping table would be used. + * The int returned is the field datatype, not an error code. */ -int segy_init_field_data(int field, segy_field_data* fd); - -int segy_get_field_u8( const char* header, int field, uint8_t* val ); -int segy_get_field_u16( const char* header, int field, uint16_t* val ); -int segy_get_field_u64( const char* header, int field, uint64_t* val ); -int segy_get_field_i16( const char* header, int field, int16_t* val ); -int segy_get_field_i32( const char* header, int field, int32_t* val ); -int segy_get_field_f64( const char* header, int field, double* val ); +int segy_field_datatype( int field ); + +int segy_get_field( const char* header, int field, segy_field_data* fd ); +int segy_set_field( char* header, int field, segy_field_data fd ); + int segy_get_field_int( const char* header, int field, int* f ); -segy_field_data segy_get_field( const char* header, int field); -int segy_field_data_to_int( const segy_field_data* fd, int* val ); - -int segy_set_field_i16( char* header, const int field, const int16_t val ); -int segy_set_field_i32( char* header, const int field, const int32_t val ); -int segy_set_field_u16( char* header, const int field, const uint16_t val ); -int segy_set_field_u64( char* header, const int field, const uint64_t val ); -int segy_set_field_f64( char* header, const int field, const double val ); int segy_set_field_int( char* header, const int field, const int val ); -int segy_set_field( char* header, segy_field_data* fd ); int segy_field_forall( segy_datasource*, int field, diff --git a/lib/src/segy.c b/lib/src/segy.c index 2520381b..7014c7f0 100644 --- a/lib/src/segy.c +++ b/lib/src/segy.c @@ -815,62 +815,77 @@ int segy_close( segy_datasource* ds ) { return SEGY_OK; } -static int get_field( const char* header, segy_field_data* fd) { +int segy_field_datatype( int field ) { + if( field > 0 && field < SEGY_TRACE_HEADER_SIZE ) { + return tr_field_type[field]; + } else if( field > SEGY_TEXT_HEADER_SIZE && field < SEGY_TEXT_HEADER_SIZE + SEGY_BINARY_HEADER_SIZE ) { + return bin_field_type[field - SEGY_TEXT_HEADER_SIZE]; + } else { + return SEGY_UNDEFINED_FIELD; + } +} +int segy_get_field( const char* header, int field, segy_field_data* fd ) { + int offset = field - 1; + if (offset >= SEGY_TEXT_HEADER_SIZE) { + offset -= SEGY_TEXT_HEADER_SIZE; + } uint64_t val; + + fd->datatype = segy_field_datatype( field ); switch ( fd->datatype ) { case SEGY_SIGNED_INTEGER_8_BYTE: - memcpy( &(fd->value.i64), header + (fd->field_index -1), formatsize( fd->datatype ) ); + memcpy( &(fd->value.i64), header + offset, formatsize( fd->datatype ) ); fd->value.i64 = be64toh( fd->value.i64 ); return SEGY_OK; case SEGY_SIGNED_INTEGER_4_BYTE: - memcpy( &(fd->value.i32), header + (fd->field_index -1), formatsize( fd->datatype ) ); + memcpy( &(fd->value.i32), header + offset, formatsize( fd->datatype ) ); fd->value.i32 = be32toh( fd->value.i32 ); return SEGY_OK; case SEGY_SIGNED_SHORT_2_BYTE: - memcpy( &(fd->value.i16), header + (fd->field_index -1), formatsize( fd->datatype ) ); + memcpy( &(fd->value.i16), header + offset, formatsize( fd->datatype ) ); fd->value.i16 = be16toh( fd->value.i16 ); return SEGY_OK; case SEGY_SIGNED_CHAR_1_BYTE: - memcpy( &(fd->value.i8), header + (fd->field_index -1), formatsize( fd->datatype ) ); + memcpy( &(fd->value.i8), header + offset, formatsize( fd->datatype ) ); return SEGY_OK; case SEGY_UNSIGNED_INTEGER_8_BYTE: - memcpy( &(fd->value.u64), header + (fd->field_index -1), formatsize( fd->datatype ) ); + memcpy( &(fd->value.u64), header + offset, formatsize( fd->datatype ) ); fd->value.u64 = be64toh( fd->value.u64 ); return SEGY_OK; case SEGY_UNSIGNED_INTEGER_4_BYTE: - memcpy( &(fd->value.u32), header + (fd->field_index -1), formatsize( fd->datatype ) ); + memcpy( &(fd->value.u32), header + offset, formatsize( fd->datatype ) ); fd->value.u32 = be32toh( fd->value.u32 ); return SEGY_OK; case SEGY_UNSIGNED_SHORT_2_BYTE: - memcpy( &(fd->value.u16), header + (fd->field_index -1), formatsize( fd->datatype ) ); + memcpy( &(fd->value.u16), header + offset, formatsize( fd->datatype ) ); fd->value.u16 = be16toh( fd->value.u16 ); return SEGY_OK; case SEGY_UNSIGNED_CHAR_1_BYTE: - memcpy( &(fd->value.u8), header + (fd->field_index -1), formatsize( fd->datatype ) ); + memcpy( &(fd->value.u8), header + offset, formatsize( fd->datatype ) ); return SEGY_OK; case SEGY_IEEE_FLOAT_8_BYTE: - memcpy( &(fd->value.f64), header + (fd->field_index -1), formatsize( fd->datatype ) ); + memcpy( &(fd->value.f64), header + offset, formatsize( fd->datatype ) ); memcpy( &val, &(fd->value.f64), sizeof( uint64_t ) ); val = be64toh( val ); memcpy( &(fd->value.f64), &val, sizeof( uint64_t ) ); return SEGY_OK; default: - return SEGY_INVALID_FIELD_DATATYPE; + return SEGY_INVALID_FIELD; } } -int segy_field_data_to_int( const segy_field_data* fd, int* val ) { +static int fd_get_int( const segy_field_data* fd, int* val ) { switch( fd->datatype ) { case SEGY_SIGNED_INTEGER_4_BYTE: @@ -898,171 +913,79 @@ int segy_field_data_to_int( const segy_field_data* fd, int* val ) { } } -int segy_init_field_data(int field, segy_field_data* fd) { - if ( field > 0 && field < SEGY_TRACE_HEADER_SIZE ) { - fd->field_index = field; - fd->field_offset = 0; - fd->datatype = tr_field_type[ fd->field_index ]; - } - else if ( field > SEGY_TEXT_HEADER_SIZE && field < SEGY_TEXT_HEADER_SIZE + SEGY_BINARY_HEADER_SIZE ) { - fd->field_index = field - SEGY_TEXT_HEADER_SIZE; - fd->field_offset = SEGY_TEXT_HEADER_SIZE; - fd->datatype = bin_field_type[ fd->field_index ]; - } - else - return SEGY_INVALID_FIELD; - if ( fd->datatype == SEGY_UNDEFINED_FIELD ) - return SEGY_INVALID_FIELD; - return SEGY_OK; -} - -int segy_get_field_u8( const char* header, int field, uint8_t* val ) { - segy_field_data fd; - int err = segy_init_field_data( field, &fd ); - if ( err != SEGY_OK ) return err; - err = get_field( header, &fd ); - if( err != SEGY_OK ) return err; - if ( fd.datatype != SEGY_UNSIGNED_CHAR_1_BYTE ) - return SEGY_INVALID_FIELD_DATATYPE; - *val = fd.value.u8; - return SEGY_OK; -} - -int segy_get_field_u16( const char* header, int field, uint16_t* val ) { - segy_field_data fd; - int err = segy_init_field_data( field, &fd ); - if ( err != SEGY_OK ) return err; - err = get_field( header, &fd ); - if( err != SEGY_OK ) return err; - if ( fd.datatype != SEGY_UNSIGNED_SHORT_2_BYTE ) - return SEGY_INVALID_FIELD_DATATYPE; - *val = fd.value.u16; - return SEGY_OK; -} - -int segy_get_field_u64( const char* header, int field, uint64_t* val ) { +int segy_get_field_int( const char* header, int field, int* val ) { segy_field_data fd; - int err = segy_init_field_data( field, &fd ); + int err = segy_get_field(header, field, &fd); if ( err != SEGY_OK ) return err; - err = get_field( header, &fd ); - if( err != SEGY_OK ) return err; - if ( fd.datatype != SEGY_UNSIGNED_INTEGER_8_BYTE ) - return SEGY_INVALID_FIELD_DATATYPE; - *val = fd.value.u64; - return SEGY_OK; + return fd_get_int( &fd, val ); } -int segy_get_field_i16( const char* header, int field, int16_t* val ) { - segy_field_data fd; - int err = segy_init_field_data( field, &fd ); - if ( err != SEGY_OK ) return err; - err = get_field( header, &fd ); - if( err != SEGY_OK ) return err; - if ( fd.datatype != SEGY_SIGNED_SHORT_2_BYTE ) - return SEGY_INVALID_FIELD_DATATYPE; - *val = fd.value.i16; - return SEGY_OK; -} +int segy_set_field( char* header, int field, segy_field_data fd ) { + int offset = field - 1; + if (offset >= SEGY_TEXT_HEADER_SIZE) { + offset -= SEGY_TEXT_HEADER_SIZE; + } -int segy_get_field_i32( const char* header, int field, int32_t* val ) { - segy_field_data fd; - int err = segy_init_field_data( field, &fd ); - if ( err != SEGY_OK ) return err; - err = get_field( header, &fd ); - if( err != SEGY_OK ) return err; - if ( fd.datatype != SEGY_SIGNED_INTEGER_4_BYTE ) - return SEGY_INVALID_FIELD_DATATYPE; - *val = fd.value.i32; - return SEGY_OK; -} + segy_field_value fv = fd.value; + uint64_t val; -int segy_get_field_f64( const char* header, int field, double* val ) { - segy_field_data fd; - int err = segy_init_field_data( field, &fd ); - if ( err != SEGY_OK ) return err; - err = get_field( header, &fd ); - if( err != SEGY_OK ) return err; - if ( fd.datatype != SEGY_IEEE_FLOAT_8_BYTE ) + uint8_t datatype = segy_field_datatype( field ); + if (fd.datatype != datatype) { return SEGY_INVALID_FIELD_DATATYPE; - *val = fd.value.f64; - return SEGY_OK; -} - -int segy_get_field_int( const char* header, int field, int* val ) { - segy_field_data fd; - int err = segy_init_field_data( field, &fd ); - if ( err != SEGY_OK ) return err; - err = get_field( header, &fd ); - if( err != SEGY_OK ) return err; - return segy_field_data_to_int( &fd, val ); -} - -segy_field_data segy_get_field( const char* header, int field) { - segy_field_data fd; - fd.error = segy_init_field_data( field, &fd ); - if ( fd.error != SEGY_OK ) return fd; - fd.error = get_field( header, &fd ); - return fd; -} - -static int set_field( char* header, - const segy_field_data* fd ) { + } - segy_field_value fv = fd->value; - uint64_t val; - switch ( fd->datatype ) { + switch ( fd.datatype ) { case SEGY_SIGNED_INTEGER_8_BYTE: fv.i64 = htobe64( fv.i64 ); - memcpy( header + (fd->field_index - 1), &(fv.i64), formatsize( fd->datatype )); + memcpy( header + offset, &(fv.i64), formatsize( fd.datatype )); return SEGY_OK; case SEGY_SIGNED_INTEGER_4_BYTE: fv.i32 = htobe32( fv.i32 ); - memcpy( header + (fd->field_index - 1), &(fv.i32), formatsize( fd->datatype )); + memcpy( header + offset, &(fv.i32), formatsize( fd.datatype )); return SEGY_OK; case SEGY_SIGNED_SHORT_2_BYTE: fv.i16 = htobe16( fv.i16 ); - memcpy( header + (fd->field_index - 1), &(fv.i16), formatsize( fd->datatype )); + memcpy( header + offset, &(fv.i16), formatsize( fd.datatype )); return SEGY_OK; case SEGY_SIGNED_CHAR_1_BYTE: - memcpy( header + (fd->field_index - 1), &(fv.i8), formatsize( fd->datatype )); + memcpy( header + offset, &(fv.i8), formatsize( fd.datatype )); return SEGY_OK; case SEGY_UNSIGNED_INTEGER_8_BYTE: fv.u64 = htobe64( fv.u64 ); - memcpy( header + (fd->field_index - 1), &(fv.u64), formatsize( fd->datatype )); + memcpy( header + offset, &(fv.u64), formatsize( fd.datatype )); return SEGY_OK; case SEGY_UNSIGNED_INTEGER_4_BYTE: fv.u32 = htobe32( fv.u32 ); - memcpy( header + (fd->field_index - 1), &(fv.u32), formatsize( fd->datatype )); + memcpy( header + offset, &(fv.u32), formatsize( fd.datatype )); return SEGY_OK; case SEGY_UNSIGNED_SHORT_2_BYTE: fv.u16 = htobe16( fv.u16 ); - memcpy( header + (fd->field_index - 1), &(fv.u16), formatsize( fd->datatype )); + memcpy( header + offset, &(fv.u16), formatsize( fd.datatype )); return SEGY_OK; case SEGY_UNSIGNED_CHAR_1_BYTE: - memcpy( header + (fd->field_index - 1), &(fv.u8), formatsize( fd->datatype )); + memcpy( header + offset, &(fv.u8), formatsize( fd.datatype )); return SEGY_OK; case SEGY_IEEE_FLOAT_8_BYTE: memcpy( &val, &(fv.f64), sizeof( uint64_t ) ); val = htobe64( val ); memcpy( &(fv.f64), &val, sizeof( uint64_t ) ); - memcpy( header + (fd->field_index - 1), &(fv.f64), formatsize( fd->datatype )); + memcpy( header + offset, &(fv.f64), formatsize( fd.datatype )); return SEGY_OK; default: - return SEGY_INVALID_FIELD_DATATYPE; + return SEGY_INVALID_FIELD; } } - static int fd_set_int( segy_field_data* fd, int val ) { switch( fd->datatype ) { case SEGY_SIGNED_INTEGER_4_BYTE: @@ -1098,81 +1021,15 @@ static int fd_set_int( segy_field_data* fd, int val ) { } } -int segy_set_field_i16( char* header, const int field, const int16_t val ) { - segy_field_data fd; - int err = segy_init_field_data( field, &fd ); - if ( err != SEGY_OK ) return err; - - if ( fd.datatype != SEGY_SIGNED_SHORT_2_BYTE ) - return SEGY_INVALID_FIELD_DATATYPE; - - fd.value.i16 = val; - return set_field( header, &fd ); -} - -int segy_set_field_i32( char* header, const int field, const int32_t val ) { - segy_field_data fd; - int err = segy_init_field_data( field, &fd ); - if ( err != SEGY_OK ) return err; - - if ( fd.datatype != SEGY_SIGNED_INTEGER_4_BYTE ) - return SEGY_INVALID_FIELD_DATATYPE; - - fd.value.i32 = val; - return set_field( header, &fd ); -} - -int segy_set_field_u16( char* header, const int field, const uint16_t val ) { - segy_field_data fd; - int err = segy_init_field_data( field, &fd ); - if ( err != SEGY_OK ) return err; - - if ( fd.datatype != SEGY_UNSIGNED_SHORT_2_BYTE ) - return SEGY_INVALID_FIELD_DATATYPE; - - fd.value.u16 = val; - return set_field( header, &fd ); -} - -int segy_set_field_u64( char* header, const int field, const uint64_t val ) { - segy_field_data fd; - int err = segy_init_field_data( field, &fd ); - if ( err != SEGY_OK ) return err; - - if ( fd.datatype != SEGY_UNSIGNED_INTEGER_8_BYTE ) - return SEGY_INVALID_FIELD_DATATYPE; - - fd.value.u64 = val; - return set_field( header, &fd ); -} - -int segy_set_field_f64( char* header, const int field, const double val ) { - segy_field_data fd; - int err = segy_init_field_data( field, &fd ); - if ( err != SEGY_OK ) return err; - - if ( fd.datatype != SEGY_IEEE_FLOAT_8_BYTE ) - return SEGY_INVALID_FIELD_DATATYPE; - - fd.value.f64 = val; - return set_field( header, &fd ); -} - int segy_set_field_int( char* header, const int field, const int val ) { - segy_field_data fd; - int err = segy_init_field_data( field, &fd ); - if ( err != SEGY_OK ) return err; - - err = fd_set_int( &fd, val ); - if ( err != SEGY_OK ) return err; + fd.datatype = segy_field_datatype( field ); + if ( fd.datatype == SEGY_UNDEFINED_FIELD ) return SEGY_INVALID_FIELD; - return set_field( header, &fd ); -} + int err = fd_set_int( &fd, val ); + if( err != SEGY_OK ) return err; -int segy_set_field( char* header, segy_field_data* fd ) { - fd->error = set_field( header, fd ); - return fd->error; + return segy_set_field( header, field, fd ); } static int slicelength( int start, int stop, int step ) { @@ -1246,11 +1103,9 @@ int segy_field_forall( segy_datasource* ds, if( err != 0 ) return SEGY_DS_READ_ERROR; segy_field_data fd; - err = segy_init_field_data(field, &fd); - if ( err != SEGY_OK ) return err; - err = get_field( header, &fd ); + err = segy_get_field( header, field, &fd ); if( err != 0 ) return err; - err = segy_field_data_to_int( &fd, &f ); + err = fd_get_int( &fd, &f ); if( err != 0 ) return err; if (ds->lsb) f = bswap_header_word(f, formatsize( fd.datatype )); *buf = f; @@ -1345,8 +1200,8 @@ int segy_write_binheader( segy_datasource* ds, const char* buf ) { } int segy_format( const char* binheader ) { - int16_t format = 0; - segy_get_field_i16( binheader, SEGY_BIN_FORMAT, &format ); + int format = 0; + segy_get_field_int( binheader, SEGY_BIN_FORMAT, &format ); return format; } @@ -1372,12 +1227,12 @@ int segy_set_endianness( segy_datasource* ds, int endianness) { } int segy_samples( const char* binheader ) { - uint16_t samples = 0; - segy_get_field_u16( binheader, SEGY_BIN_SAMPLES, &samples ); + int samples = 0; + segy_get_field_int( binheader, SEGY_BIN_SAMPLES, &samples ); samples = (int32_t)((uint16_t)samples); - int32_t ext_samples = 0; - segy_get_field_i32(binheader, SEGY_BIN_EXT_SAMPLES, &ext_samples); + int ext_samples = 0; + segy_get_field_int(binheader, SEGY_BIN_EXT_SAMPLES, &ext_samples); if (samples == 0 && ext_samples > 0) return ext_samples; @@ -1393,8 +1248,8 @@ int segy_samples( const char* binheader ) { * used, the revision flag is also appropriately set to >= 2. Negative * values are ignored, as it's likely just noise. */ - uint8_t revision = 0; - segy_get_field_u8(binheader, SEGY_BIN_SEGY_REVISION, &revision); + int revision = 0; + segy_get_field_int(binheader, SEGY_BIN_SEGY_REVISION, &revision); if (revision >= 2 && ext_samples > 0) return ext_samples; @@ -1413,8 +1268,8 @@ int segy_trsize( int format, int samples ) { } long segy_trace0( const char* binheader ) { - int16_t extra_headers = 0; - segy_get_field_i16( binheader, SEGY_BIN_EXT_HEADERS, &extra_headers ); + int extra_headers = 0; + segy_get_field_int( binheader, SEGY_BIN_EXT_HEADERS, &extra_headers ); return SEGY_TEXT_HEADER_SIZE + SEGY_BINARY_HEADER_SIZE + SEGY_TEXT_HEADER_SIZE * extra_headers; @@ -1621,11 +1476,11 @@ int segy_sample_interval( segy_datasource* ds, float fallback, float* dt ) { return err; } - int16_t bindt = 0; - int16_t trdt = 0; + int bindt = 0; + int trdt = 0; - segy_get_field_i16( bin_header, SEGY_BIN_INTERVAL, &bindt ); - segy_get_field_i16( trace_header, SEGY_TR_SAMPLE_INTER, &trdt ); + segy_get_field_int( bin_header, SEGY_BIN_INTERVAL, &bindt ); + segy_get_field_int( trace_header, SEGY_TR_SAMPLE_INTER, &trdt ); float binary_header_dt = (float) bindt; float trace_header_dt = (float) trdt; @@ -2672,18 +2527,18 @@ static int scaled_cdp( segy_datasource* ds, float* cdpy, long trace0, int trace_bsize ) { - int32_t x, y; - int16_t scalar; + int x, y; + int scalar; char trheader[ SEGY_TRACE_HEADER_SIZE ]; int err = segy_traceheader( ds, traceno, trheader, trace0, trace_bsize ); if( err != 0 ) return err; - err = segy_get_field_i32( trheader, SEGY_TR_CDP_X, &x ); + err = segy_get_field_int( trheader, SEGY_TR_CDP_X, &x ); if( err != 0 ) return err; - err = segy_get_field_i32( trheader, SEGY_TR_CDP_Y, &y ); + err = segy_get_field_int( trheader, SEGY_TR_CDP_Y, &y ); if( err != 0 ) return err; - err = segy_get_field_i16( trheader, SEGY_TR_SOURCE_GROUP_SCALAR, &scalar ); + err = segy_get_field_int( trheader, SEGY_TR_SOURCE_GROUP_SCALAR, &scalar ); if( err != 0 ) return err; float scale = (float) scalar; diff --git a/lib/src/segy.def b/lib/src/segy.def index 7527e123..34bf7762 100644 --- a/lib/src/segy.def +++ b/lib/src/segy.def @@ -12,14 +12,9 @@ segy_sample_interval segy_format segy_set_format segy_set_endianness -segy_get_field_u8 -segy_get_field_u16 -segy_get_field_i16 -segy_get_field_i32 +segy_get_field +segy_set_field segy_get_field_int -segy_set_field_u16 -segy_set_field_i16 -segy_set_field_i32 segy_set_field_int segy_field_forall segy_trace_bsize diff --git a/lib/test/segy.cpp b/lib/test/segy.cpp index 7fde357b..09caf7ee 100644 --- a/lib/test/segy.cpp +++ b/lib/test/segy.cpp @@ -69,10 +69,11 @@ struct Err { bool operator == ( Err other ) const { return this->err == other.err; } bool operator != ( Err other ) const { return !(*this == other); } - static Err ok() { return SEGY_OK; } - static Err args() { return SEGY_INVALID_ARGS; } - static Err field() { return SEGY_INVALID_FIELD; } - static Err value() { return SEGY_INVALID_FIELD_VALUE; } + static Err ok() { return SEGY_OK; } + static Err args() { return SEGY_INVALID_ARGS; } + static Err field() { return SEGY_INVALID_FIELD; } + static Err value() { return SEGY_INVALID_FIELD_VALUE; } + static Err datatype() { return SEGY_INVALID_FIELD_DATATYPE; } int err; }; @@ -274,8 +275,8 @@ TEST_CASE_METHOD( smallbin, "use bin-interval when trace-interval is zero", "[c.segy]" ) { - std::int16_t hdt = arbitrary_int(); - segy_get_field_i16( bin, SEGY_BIN_INTERVAL, &hdt ); + int hdt = arbitrary_int(); + segy_get_field_int( bin, SEGY_BIN_INTERVAL, &hdt ); REQUIRE( hdt == 4000 ); float dt = arbitrary_float(); @@ -411,8 +412,8 @@ TEST_CASE_METHOD( smallheader, "valid trace-header fields can be read", "[c.segy]" ) { - int32_t ilno; - Err err = segy_get_field_i32( header, SEGY_TR_INLINE, &ilno ); + int ilno; + Err err = segy_get_field_int( header, SEGY_TR_INLINE, &ilno ); CHECK( success( err ) ); CHECK( ilno == 1 ); } @@ -420,9 +421,9 @@ TEST_CASE_METHOD( smallheader, TEST_CASE_METHOD( smallheader, "zero header field is an argument error", "[c.segy]" ) { - const int32_t input_value = arbitrary_int(); + const int input_value = arbitrary_int(); auto value = input_value; - Err err = segy_get_field_i32( header, 0, &value ); + Err err = segy_get_field_int( header, 0, &value ); CHECK( err == Err::field() ); CHECK( value == input_value ); @@ -431,9 +432,9 @@ TEST_CASE_METHOD( smallheader, TEST_CASE_METHOD( smallheader, "negative header field is an argument error", "[c.segy]" ) { - const int32_t input_value = arbitrary_int(); + const int input_value = arbitrary_int(); auto value = input_value; - Err err = segy_get_field_i32( header, -1, &value ); + Err err = segy_get_field_int( header, -1, &value ); CHECK( err == Err::field() ); CHECK( value == input_value ); @@ -442,9 +443,9 @@ TEST_CASE_METHOD( smallheader, TEST_CASE_METHOD( smallheader, "unaligned header field is an argument error", "[c.segy]" ) { - const int32_t input_value = arbitrary_int(); + const int input_value = arbitrary_int(); auto value = input_value; - Err err = segy_get_field_i32( header, SEGY_TR_INLINE + 1, &value ); + Err err = segy_get_field_int( header, SEGY_TR_INLINE + 1, &value ); CHECK( err == Err::field() ); CHECK( value == input_value ); @@ -1291,7 +1292,7 @@ TEST_CASE( "setting unaligned header-field fails", char header[ SEGY_TRACE_HEADER_SIZE ]; const int32_t v = arbitrary_int(); - Err err = segy_set_field_i32( header, SEGY_TR_INLINE + 1, v ); + Err err = segy_set_field_int( header, SEGY_TR_INLINE + 1, v ); CHECK( err == Err::field() ); } @@ -1309,7 +1310,7 @@ TEST_CASE( "setting too large header-field fails", char header[ SEGY_TRACE_HEADER_SIZE ]; const int32_t v = arbitrary_int(); - Err err = segy_set_field_i32( header, SEGY_TRACE_HEADER_SIZE + 10, v ); + Err err = segy_set_field_int( header, SEGY_TRACE_HEADER_SIZE + 10, v ); CHECK( err == Err::field() ); } @@ -1319,12 +1320,12 @@ TEST_CASE( "setting correct header fields succeeds", const int32_t input = 1; const int field = SEGY_TR_INLINE; - Err err = segy_set_field_i32( header, field, input ); + Err err = segy_set_field_int( header, field, input ); CHECK( success( err ) ); int32_t output; - err = segy_get_field_i32( header, field, &output ); + err = segy_get_field_int( header, field, &output ); CHECK( success( err ) ); CHECK( output == input ); @@ -1342,17 +1343,17 @@ SCENARIO( "modifying trace header", "[c.segy]" ) { WHEN( "writing iline no" ) { char header[ SEGY_TRACE_HEADER_SIZE ] = {}; - Err err = segy_set_field_i32( header, SEGY_TR_INLINE, 2 ); + Err err = segy_set_field_int( header, SEGY_TR_INLINE, 2 ); CHECK( err == Err::ok() ); - err = segy_set_field_i16( header, SEGY_TR_SOURCE_GROUP_SCALAR, -100 ); + err = segy_set_field_int( header, SEGY_TR_SOURCE_GROUP_SCALAR, -100 ); CHECK( err == Err::ok() ); THEN( "the header buffer is updated") { int ilno = 0; - int16_t scale = 0; - err = segy_get_field_i32( header, SEGY_TR_INLINE, &ilno ); + int scale = 0; + err = segy_get_field_int( header, SEGY_TR_INLINE, &ilno ); CHECK( err == Err::ok() ); - err = segy_get_field_i16( header, SEGY_TR_SOURCE_GROUP_SCALAR, &scale ); + err = segy_get_field_int( header, SEGY_TR_SOURCE_GROUP_SCALAR, &scale ); CHECK( err == Err::ok() ); CHECK( ilno == 2 ); @@ -1379,12 +1380,12 @@ SCENARIO( "modifying trace header", "[c.segy]" ) { THEN( "changes are observable on disk" ) { char fresh[ SEGY_TRACE_HEADER_SIZE ] = {}; int ilno = 0; - int16_t scale = 0; + int scale = 0; err = segy_traceheader( fp, 5, fresh, trace0, trace_bsize ); CHECK( err == Err::ok() ); - err = segy_get_field_i32( fresh, SEGY_TR_INLINE, &ilno ); + err = segy_get_field_int( fresh, SEGY_TR_INLINE, &ilno ); CHECK( err == Err::ok() ); - err = segy_get_field_i16( fresh, SEGY_TR_SOURCE_GROUP_SCALAR, &scale ); + err = segy_get_field_int( fresh, SEGY_TR_SOURCE_GROUP_SCALAR, &scale ); CHECK( err == Err::ok() ); CHECK( ilno == 2 ); @@ -1858,7 +1859,7 @@ SCENARIO( "reading a 2-byte int file", "[c.segy][2-byte]" ) { CHECK( err == Err::ok() ); int ilno = 0; - err = segy_get_field_i32( buf, SEGY_TR_INLINE, &ilno ); + err = segy_get_field_int( buf, SEGY_TR_INLINE, &ilno ); CHECK( err == Err::ok() ); CHECK( ilno == 111 ); } @@ -1869,7 +1870,7 @@ SCENARIO( "reading a 2-byte int file", "[c.segy][2-byte]" ) { CHECK( err == Err::field() ); CHECK( x == -1 ); - err = segy_get_field_i32( buf, SEGY_TR_INLINE + 1, &x ); + err = segy_get_field_int( buf, SEGY_TR_INLINE + 1, &x ); CHECK( err == Err::field() ); CHECK( x == -1 ); } @@ -2010,14 +2011,14 @@ TEST_CASE("1-byte header words are correctly read", "[c.segy]") { header[300] = 0x01; header[301] = 0x02; - std::uint8_t one; - std::uint8_t two; + int one; + int two; - Err err = segy_get_field_u8(header.data(), SEGY_BIN_SEGY_REVISION, &one); + Err err = segy_get_field_int(header.data(), SEGY_BIN_SEGY_REVISION, &one); CHECK(err == Err::ok()); CHECK(one == 0x01); - err = segy_get_field_u8(header.data(), SEGY_BIN_SEGY_REVISION_MINOR, &two); + err = segy_get_field_int(header.data(), SEGY_BIN_SEGY_REVISION_MINOR, &two); CHECK(err == Err::ok()); CHECK(two == 0x02); } @@ -2053,10 +2054,11 @@ TEST_CASE("segy_get_field reads values correctly", "[c.segy]" ) { header[SEGY_TR_TRACE_ID-1] = b1; header[SEGY_TR_TRACE_ID-0] = b0; - int16_t read_value; - Err err = segy_get_field_i16( header, SEGY_TR_TRACE_ID, &read_value ); + segy_field_data read_value; + Err err = segy_get_field( header, SEGY_TR_TRACE_ID, &read_value ); CHECK( success( err ) ); - CHECK( read_value == value ); + CHECK( read_value.datatype == SEGY_SIGNED_SHORT_2_BYTE ); + CHECK( read_value.value.i16 == value ); } } @@ -2066,7 +2068,11 @@ TEST_CASE("segy_set_field write values correctly", "[c.segy]" ) { SECTION("test edge cases int16") { int16_t value = GENERATE(0, 1, -1, 0x0102, 0x0201, -32767, -32766); - Err err = segy_set_field_i16( header, SEGY_TR_TRACE_ID, value ); + + segy_field_data fd; + fd.datatype = SEGY_SIGNED_SHORT_2_BYTE; + fd.value.i16 = value; + Err err = segy_set_field( header, SEGY_TR_TRACE_ID, fd ); CHECK( err == Err::ok() ); uint8_t b0 = header[SEGY_TR_TRACE_ID-0]; @@ -2080,9 +2086,17 @@ TEST_CASE("segy_set_field write invalid value", "[c.segy]" ) { char header[ SEGY_TRACE_HEADER_SIZE ] = { 0 }; - SECTION("test value outside of int16 range") { + SECTION("test value outside of int16 range for segy_set_field_int") { int32_t value = 0xFFFF + 1; Err err = segy_set_field_int( header, SEGY_TR_TRACE_ID, value ); CHECK( err == Err::value() ); } + + SECTION("test mismatched type") { + segy_field_data fd; + fd.value.i16 = 42; + fd.datatype = SEGY_SIGNED_INTEGER_4_BYTE; + Err err = segy_set_field( header, SEGY_TR_TRACE_ID, fd ); + CHECK( err == Err::datatype() ); + } } diff --git a/mex/segy_get_traces_mex.c b/mex/segy_get_traces_mex.c index 78ced546..cd2a9642 100644 --- a/mex/segy_get_traces_mex.c +++ b/mex/segy_get_traces_mex.c @@ -63,8 +63,8 @@ void mexFunction(int nlhs, mxArray *plhs[], segy_to_native( fmt.format, bufsize, mxGetData( plhs[ 0 ] ) ); - int16_t interval; - segy_get_field_i16( binary, SEGY_BIN_INTERVAL, &interval ); + int interval; + segy_get_field_int( binary, SEGY_BIN_INTERVAL, &interval ); plhs[ 1 ] = mxCreateDoubleScalar( interval ); plhs[ 2 ] = mxCreateDoubleScalar( fmt.format ); diff --git a/python/segyio/segyio.cpp b/python/segyio/segyio.cpp index 5668cee8..aed2553a 100644 --- a/python/segyio/segyio.cpp +++ b/python/segyio/segyio.cpp @@ -1696,9 +1696,10 @@ PyObject* getfield( PyObject*, PyObject *args ) { buffer.len() != SEGY_TRACE_HEADER_SIZE ) return BufferError( "buffer too small" ); - segy_field_data fd = segy_get_field( buffer.buf< const char >(), field ); - if( fd.error != SEGY_OK ) - return KeyError( "Got error code %d when requesting field %d", fd.error, field ); + segy_field_data fd; + int err = segy_get_field( buffer.buf< const char >(), field, &fd ); + if( err != SEGY_OK ) + return KeyError( "Got error code %d when requesting field %d", err, field ); switch ( fd.datatype ) { @@ -1745,10 +1746,7 @@ PyObject* putfield( PyObject*, PyObject *args ) { int field = (int)PyLong_AsLong(field_arg); segy_field_data fd; - int err = segy_init_field_data(field, &fd); - - if( err != SEGY_OK ) - return KeyError( "Failed to initialize field %d got error %d", field, err ); + fd.datatype = segy_field_datatype(field); switch ( fd.datatype ) { case SEGY_UNSIGNED_INTEGER_8_BYTE: @@ -1848,7 +1846,7 @@ PyObject* putfield( PyObject*, PyObject *args ) { return KeyError( "Field %d has unknown datatype %d", field, fd.datatype ); } - err = segy_set_field( buffer.buf< char >(), &fd ); + int err = segy_set_field( buffer.buf< char >(), field, fd ); switch( err ) { case SEGY_OK: