From 425e52f55a62e38ce283f46d9521ff309b2dacdc Mon Sep 17 00:00:00 2001 From: Hong Chen Date: Mon, 22 Jun 2026 17:04:57 -0500 Subject: [PATCH 1/5] Add data recording support for STL (vector, deque, and array) support of supported data types. --- include/trick/ReferenceUtils.hh | 34 ++ .../Ref_Logs/log_STL_DR_Master.csv | 12 + .../Ref_Logs/log_STL_DR_bin_Master.trk | Bin 0 -> 1821 bytes test/SIM_stls/RUN_test_dr/input_dr.py | 103 ++++++ test/SIM_stls/models/STLCheckpoint.cpp | 5 + test/SIM_stls/models/STLCheckpoint.hh | 14 +- test_sims.yml | 6 + .../sim_services/DataRecord/DRAscii.cpp | 156 ++++----- .../sim_services/DataRecord/DRBinary.cpp | 97 +++--- .../sim_services/DataRecord/DRHDF5.cpp | 310 ++++++++++-------- .../DataRecord/DataRecordGroup.cpp | 47 ++- .../MemoryManager/ReferenceUtils.cpp | 87 +++++ .../VariableServer/VariableReference.cpp | 118 ++----- 13 files changed, 615 insertions(+), 374 deletions(-) create mode 100644 include/trick/ReferenceUtils.hh create mode 100644 test/SIM_stls/RUN_test_dr/Ref_Logs/log_STL_DR_Master.csv create mode 100644 test/SIM_stls/RUN_test_dr/Ref_Logs/log_STL_DR_bin_Master.trk create mode 100644 test/SIM_stls/RUN_test_dr/input_dr.py create mode 100644 trick_source/sim_services/MemoryManager/ReferenceUtils.cpp diff --git a/include/trick/ReferenceUtils.hh b/include/trick/ReferenceUtils.hh new file mode 100644 index 000000000..120e9cbb1 --- /dev/null +++ b/include/trick/ReferenceUtils.hh @@ -0,0 +1,34 @@ +#ifndef REFERENCE_UTILS_HH +#define REFERENCE_UTILS_HH + +/* + PURPOSE: ( Provides helper functions for working with REF2. ) +*/ + +#include "trick/reference.h" + +namespace Trick +{ + + class ReferenceUtils + { + public: + // Returns true when ref represents an access that went through an STL container: + // stl_present == 1 (STL indexed somewhere in the path, e.g. xxx[2].yyy.www) + // OR attr->type == TRICK_STL with the reference ending in ']' (e.g. vec[0]) + static bool is_stl_ref(const REF2* ref); + + // Returns the effective TRICK_TYPE for value interpretation: + // TRICK_STL whose reference ends with ']' -> attr->stl_elem_type + // everything else -> attr->type + static TRICK_TYPE effective_trick_type(const REF2* ref); + + // Returns the effective byte size for buffer allocation / copying: + // TRICK_STL whose reference ends with ']' -> sizeof(stl_elem_type) + // everything else -> attr->size + static size_t effective_trick_size(const REF2* ref); + }; + +} // namespace Trick + +#endif // REFERENCE_UTILS_HH diff --git a/test/SIM_stls/RUN_test_dr/Ref_Logs/log_STL_DR_Master.csv b/test/SIM_stls/RUN_test_dr/Ref_Logs/log_STL_DR_Master.csv new file mode 100644 index 000000000..f7a666d75 --- /dev/null +++ b/test/SIM_stls/RUN_test_dr/Ref_Logs/log_STL_DR_Master.csv @@ -0,0 +1,12 @@ +sys.exec.out.time {s},the_object.stlc.double_vector[0] {1},the_object.stlc.double_vector[1] {1},the_object.stlc.double_vector[2] {1},the_object.stlc.float_deque[0] {1},the_object.stlc.float_deque[1] {1},the_object.stlc.float_deque[2] {1},the_object.stlc.int_array[0] {1},the_object.stlc.int_array[1] {1},the_object.stlc.int_array[2] {1},the_object.stlc.int_array[3] {1},the_object.stlc.vec_user_simple[0].b {1},the_object.stlc.vec_user_simple[0].a[0] {1},the_object.stlc.vec_user_simple[0].a[2] {1},the_object.stlc.vec_user_defined[0].a {1},the_object.stlc.vec_user_defined[0].vec[0] {1},the_object.stlc.vec_user_defined[0].vec[2] {1} + 0, 4, 5, 6, 98.699997, 65.400002, 32.099998,10,20,30,40,8888888888,0,2,888,0,2 + 0.1, 4, 5, 6, 98.699997, 65.400002, 32.099998,10,20,30,40,8888888888,0,2,888,0,2 + 0.2, 4, 5, 6, 98.699997, 65.400002, 32.099998,10,20,30,40,8888888888,0,2,888,0,2 + 0.3, 4, 5, 6, 98.699997, 65.400002, 32.099998,10,20,30,40,8888888888,0,2,888,0,2 + 0.4, 4, 5, 6, 98.699997, 65.400002, 32.099998,10,20,30,40,8888888888,0,2,888,0,2 + 0.5, 4, 5, 6, 98.699997, 65.400002, 32.099998,10,20,30,40,8888888888,0,2,888,0,2 + 0.6, 4, 5, 6, 98.699997, 65.400002, 32.099998,10,20,30,40,8888888888,0,2,888,0,2 + 0.7, 4, 5, 6, 98.699997, 65.400002, 32.099998,10,20,30,40,8888888888,0,2,888,0,2 + 0.8, 4, 5, 6, 98.699997, 65.400002, 32.099998,10,20,30,40,8888888888,0,2,888,0,2 + 0.9, 4, 5, 6, 98.699997, 65.400002, 32.099998,10,20,30,40,8888888888,0,2,888,0,2 + 1, 4, 5, 6, 98.699997, 65.400002, 32.099998,10,20,30,40,8888888888,0,2,888,0,2 diff --git a/test/SIM_stls/RUN_test_dr/Ref_Logs/log_STL_DR_bin_Master.trk b/test/SIM_stls/RUN_test_dr/Ref_Logs/log_STL_DR_bin_Master.trk new file mode 100644 index 0000000000000000000000000000000000000000..9633f8ac2d0a1e71f63cd47b46e8053745273ebc GIT binary patch literal 1821 zcmWG3%1qAIH8jxm5oBOs0O8`wV!hOg)MUN<(h|Lr%-mE)kRUgZ-~eI;ATG&Bjn7ZY zN=+`&D=x`N)=SARP0C4)F9QnX7eyPyf;1QsufdR14MwOM9(CU}VOZ7N-`)7iZ=cVjOG!=3%u7uH zxiS&#N|@KQh|~r2F1kZW(Te6)pruGazyZP$fzlEVX=z8D&Yo#gGbi;U?A1g@o$^s+$W5 jhsRVmHw_G)QQcff_`amNxo6LSz#FQY3yHT6R5up@!? — expected values: 4.0, 5.0, 6.0 + drg.add_variable("the_object.stlc.double_vector[0]") + drg.add_variable("the_object.stlc.double_vector[1]") + drg.add_variable("the_object.stlc.double_vector[2]") + + # std::deque — expected values: 98.7, 65.4, 32.1 + drg.add_variable("the_object.stlc.float_deque[0]") + drg.add_variable("the_object.stlc.float_deque[1]") + drg.add_variable("the_object.stlc.float_deque[2]") + + # std::array — expected values: 10, 20, 30, 40 + drg.add_variable("the_object.stlc.int_array[0]") + drg.add_variable("the_object.stlc.int_array[1]") + drg.add_variable("the_object.stlc.int_array[2]") + drg.add_variable("the_object.stlc.int_array[3]") + + # STL-element struct member: vec_user_simple is std::vector + # vec_user_simple[i].a[j] = i+j, vec_user_simple[i].b = 8888888888 + drg.add_variable("the_object.stlc.vec_user_simple[0].b") + drg.add_variable("the_object.stlc.vec_user_simple[0].a[0]") + drg.add_variable("the_object.stlc.vec_user_simple[0].a[2]") + + # STL-element struct member: vec_user_defined is std::vector + # vec_user_defined[i].a = 888, vec_user_defined[i].vec[j] = i+j + drg.add_variable("the_object.stlc.vec_user_defined[0].a") + + # Nested STL: outer vector element's inner vector element + # vec_user_defined[0].vec = {0, 1, 2, ..., 9} + drg.add_variable("the_object.stlc.vec_user_defined[0].vec[0]") + drg.add_variable("the_object.stlc.vec_user_defined[0].vec[2]") + + drg.set_cycle(0.1) + drg.freq = trick.DR_Always + drg.thisown = 0 + trick.add_data_record_group(drg, trick.DR_Buffer) + + # --------------------------------------------------------------- + # Binary data recording group — same variables + # --------------------------------------------------------------- + drg_bin = trick.DRBinary("STL_DR_bin") + drg_bin.add_variable("the_object.stlc.double_vector[0]") + drg_bin.add_variable("the_object.stlc.double_vector[1]") + drg_bin.add_variable("the_object.stlc.double_vector[2]") + drg_bin.add_variable("the_object.stlc.float_deque[0]") + drg_bin.add_variable("the_object.stlc.float_deque[1]") + drg_bin.add_variable("the_object.stlc.float_deque[2]") + drg_bin.add_variable("the_object.stlc.int_array[0]") + drg_bin.add_variable("the_object.stlc.int_array[1]") + drg_bin.add_variable("the_object.stlc.int_array[2]") + drg_bin.add_variable("the_object.stlc.int_array[3]") + drg_bin.add_variable("the_object.stlc.vec_user_simple[0].b") + drg_bin.add_variable("the_object.stlc.vec_user_simple[0].a[0]") + drg_bin.add_variable("the_object.stlc.vec_user_simple[0].a[2]") + drg_bin.add_variable("the_object.stlc.vec_user_defined[0].a") + drg_bin.add_variable("the_object.stlc.vec_user_defined[0].vec[0]") + drg_bin.add_variable("the_object.stlc.vec_user_defined[0].vec[2]") + drg_bin.set_cycle(0.1) + drg_bin.freq = trick.DR_Always + drg_bin.thisown = 0 + trick.add_data_record_group(drg_bin, trick.DR_Buffer) + + # --------------------------------------------------------------- + # HDF5 data recording group — same variables + # --------------------------------------------------------------- + drg_hdf5 = trick.DRHDF5("STL_DR_hdf5") + drg_hdf5.add_variable("the_object.stlc.double_vector[0]") + drg_hdf5.add_variable("the_object.stlc.double_vector[1]") + drg_hdf5.add_variable("the_object.stlc.double_vector[2]") + drg_hdf5.add_variable("the_object.stlc.float_deque[0]") + drg_hdf5.add_variable("the_object.stlc.float_deque[1]") + drg_hdf5.add_variable("the_object.stlc.float_deque[2]") + drg_hdf5.add_variable("the_object.stlc.int_array[0]") + drg_hdf5.add_variable("the_object.stlc.int_array[1]") + drg_hdf5.add_variable("the_object.stlc.int_array[2]") + drg_hdf5.add_variable("the_object.stlc.int_array[3]") + drg_hdf5.add_variable("the_object.stlc.vec_user_simple[0].b") + drg_hdf5.add_variable("the_object.stlc.vec_user_simple[0].a[0]") + drg_hdf5.add_variable("the_object.stlc.vec_user_simple[0].a[2]") + drg_hdf5.add_variable("the_object.stlc.vec_user_defined[0].a") + drg_hdf5.add_variable("the_object.stlc.vec_user_defined[0].vec[0]") + drg_hdf5.add_variable("the_object.stlc.vec_user_defined[0].vec[2]") + drg_hdf5.set_cycle(0.1) + drg_hdf5.freq = trick.DR_Always + drg_hdf5.thisown = 0 + trick.add_data_record_group(drg_hdf5, trick.DR_Buffer) + + trick.exec_set_freeze_frame(0.10) + trick.stop(1.0) + +if __name__ == "__main__": + main() diff --git a/test/SIM_stls/models/STLCheckpoint.cpp b/test/SIM_stls/models/STLCheckpoint.cpp index 37dd58d57..b91d60f19 100644 --- a/test/SIM_stls/models/STLCheckpoint.cpp +++ b/test/SIM_stls/models/STLCheckpoint.cpp @@ -129,6 +129,11 @@ int STLCheckpoint::addData() { float_deque.push_back(65.4) ; float_deque.push_back(32.1) ; + int_array[0] = 10; + int_array[1] = 20; + int_array[2] = 30; + int_array[3] = 40; + string_deque.push_back("Welcome") ; string_deque.push_back("to") ; string_deque.push_back("PhoneMart") ; diff --git a/test/SIM_stls/models/STLCheckpoint.hh b/test/SIM_stls/models/STLCheckpoint.hh index be61a8c0c..be5933265 100644 --- a/test/SIM_stls/models/STLCheckpoint.hh +++ b/test/SIM_stls/models/STLCheckpoint.hh @@ -8,16 +8,16 @@ #ifndef STLCHECKPOINT_HH #define STLCHECKPOINT_HH -#include -#include -#include +#include #include +#include +#include +#include #include -#include #include -#include +#include #include - +#include class SimpleWrapper { public: @@ -61,6 +61,8 @@ class STLCheckpoint { std::multimap< int , std::string > string_data_multimap ; std::multimap< std::string , std::string > string_multimap ; + std::array int_array; + std::vector< double > double_vector ; std::vector< std::string > string_vector ; diff --git a/test_sims.yml b/test_sims.yml index 02a86f2ee..4d2ec684d 100644 --- a/test_sims.yml +++ b/test_sims.yml @@ -248,6 +248,12 @@ SIM_stls: returns: 0 RUN_test/unit_test.py: returns: 0 + RUN_test_dr/input_dr.py: + returns: 0 + compare: + - test/SIM_stls/RUN_test_dr/log_STL_DR.csv vs. test/SIM_stls/RUN_test_dr/Ref_Logs/log_STL_DR_Master.csv + - test/SIM_stls/RUN_test_dr/log_STL_DR_bin.trk vs. test/SIM_stls/RUN_test_dr/Ref_Logs/log_STL_DR_bin_Master.trk + - test/SIM_stls/RUN_test_dr/log_STL_DR_hdf5.header vs. test/SIM_stls/RUN_test_dr/Ref_Logs/log_STL_DR_hdf5_Master.header SIM_test_dr: path: test/SIM_test_dr diff --git a/trick_source/sim_services/DataRecord/DRAscii.cpp b/trick_source/sim_services/DataRecord/DRAscii.cpp index 5b1f5d902..e6318a680 100644 --- a/trick_source/sim_services/DataRecord/DRAscii.cpp +++ b/trick_source/sim_services/DataRecord/DRAscii.cpp @@ -7,16 +7,18 @@ ((Alex Lin) (NASA) (April 2009) (--) (c++ port))) */ -#include -#include -#include - #include "trick/DRAscii.hh" + +#include "trick/ReferenceUtils.hh" +#include "trick/bitfield_proto.h" #include "trick/command_line_protos.h" #include "trick/memorymanager_c_intf.h" #include "trick/message_proto.h" #include "trick/message_type.h" -#include "trick/bitfield_proto.h" + +#include +#include +#include Trick::DRAscii::DRAscii( std::string in_name, Trick::DR_Type dr_type ) : Trick::DataRecordGroup( in_name, dr_type ) { @@ -181,79 +183,83 @@ int Trick::DRAscii::copy_data_ascii_item( Trick::DataRecordBuffer * DI, int item unsigned long bf; int sbf; - address = DI->buffer + (item_num * DI->ref->attr->size) ; + int item_size = (int)Trick::ReferenceUtils::effective_trick_size(DI->ref); + TRICK_TYPE item_type = Trick::ReferenceUtils::effective_trick_type(DI->ref); + address = DI->buffer + (item_num * item_size); size_t writer_buf_spare = writer_buff + writer_buff_size - buf; - switch (DI->ref->attr->type) { - case TRICK_CHARACTER: - snprintf(buf, writer_buf_spare, "%c", *((char *) address)); - break; - - case TRICK_UNSIGNED_CHARACTER: - snprintf(buf, writer_buf_spare, "%u", *((unsigned char *) address)); - break; - - case TRICK_BOOLEAN: - snprintf(buf, writer_buf_spare, "%u", *((bool *) address)); - break; - - case TRICK_STRING: - snprintf(buf, writer_buf_spare, "%s", *((char **) address)); - break; - - case TRICK_SHORT: - snprintf(buf, writer_buf_spare, "%d", *((short *) address)); - break; - - case TRICK_UNSIGNED_SHORT: - snprintf(buf, writer_buf_spare, "%u", *((unsigned short *) address)); - break; - - case TRICK_ENUMERATED: - case TRICK_INTEGER: - snprintf(buf, writer_buf_spare, "%d", *((int *) address)); - break; - - case TRICK_UNSIGNED_INTEGER: - snprintf(buf, writer_buf_spare, "%u", *((unsigned int *) address)); - break; - - case TRICK_LONG: - snprintf(buf, writer_buf_spare, "%ld", *((long *) address)); - break; - - case TRICK_UNSIGNED_LONG: - snprintf(buf, writer_buf_spare, "%lu", *((unsigned long *) address)); - break; - - case TRICK_FLOAT: - snprintf(buf, writer_buf_spare, ascii_float_format.c_str() , *((float *) address)); - break; - - case TRICK_DOUBLE: - snprintf(buf, writer_buf_spare, ascii_double_format.c_str() , *((double *) address)); - break; - - case TRICK_BITFIELD: - sbf = GET_BITFIELD(address, DI->ref->attr->size, DI->ref->attr->index[0].start, DI->ref->attr->index[0].size); - snprintf(buf, writer_buf_spare, "%d", sbf); - break; - - case TRICK_UNSIGNED_BITFIELD: - bf = GET_UNSIGNED_BITFIELD(address, DI->ref->attr->size, DI->ref->attr->index[0].start, DI->ref->attr->index[0].size); - snprintf(buf, writer_buf_spare, "%lu", bf); - break; - - case TRICK_LONG_LONG: - snprintf(buf, writer_buf_spare, "%lld", *((long long *) address)); - break; - - case TRICK_UNSIGNED_LONG_LONG: - snprintf(buf, writer_buf_spare, "%llu", *((unsigned long long *) address)); - break; - default: - break; + switch (item_type) + { + case TRICK_CHARACTER: + snprintf(buf, writer_buf_spare, "%c", *((char*)address)); + break; + + case TRICK_UNSIGNED_CHARACTER: + snprintf(buf, writer_buf_spare, "%u", *((unsigned char*)address)); + break; + + case TRICK_BOOLEAN: + snprintf(buf, writer_buf_spare, "%u", *((bool*)address)); + break; + + case TRICK_STRING: + snprintf(buf, writer_buf_spare, "%s", *((char**)address)); + break; + + case TRICK_SHORT: + snprintf(buf, writer_buf_spare, "%d", *((short*)address)); + break; + + case TRICK_UNSIGNED_SHORT: + snprintf(buf, writer_buf_spare, "%u", *((unsigned short*)address)); + break; + + case TRICK_ENUMERATED: + case TRICK_INTEGER: + snprintf(buf, writer_buf_spare, "%d", *((int*)address)); + break; + + case TRICK_UNSIGNED_INTEGER: + snprintf(buf, writer_buf_spare, "%u", *((unsigned int*)address)); + break; + + case TRICK_LONG: + snprintf(buf, writer_buf_spare, "%ld", *((long*)address)); + break; + + case TRICK_UNSIGNED_LONG: + snprintf(buf, writer_buf_spare, "%lu", *((unsigned long*)address)); + break; + + case TRICK_FLOAT: + snprintf(buf, writer_buf_spare, ascii_float_format.c_str(), *((float*)address)); + break; + + case TRICK_DOUBLE: + snprintf(buf, writer_buf_spare, ascii_double_format.c_str(), *((double*)address)); + break; + + case TRICK_BITFIELD: + sbf = GET_BITFIELD(address, DI->ref->attr->size, DI->ref->attr->index[0].start, DI->ref->attr->index[0].size); + snprintf(buf, writer_buf_spare, "%d", sbf); + break; + + case TRICK_UNSIGNED_BITFIELD: + bf = GET_UNSIGNED_BITFIELD(address, DI->ref->attr->size, DI->ref->attr->index[0].start, + DI->ref->attr->index[0].size); + snprintf(buf, writer_buf_spare, "%lu", bf); + break; + + case TRICK_LONG_LONG: + snprintf(buf, writer_buf_spare, "%lld", *((long long*)address)); + break; + + case TRICK_UNSIGNED_LONG_LONG: + snprintf(buf, writer_buf_spare, "%llu", *((unsigned long long*)address)); + break; + default: + break; } return(0) ; diff --git a/trick_source/sim_services/DataRecord/DRBinary.cpp b/trick_source/sim_services/DataRecord/DRBinary.cpp index 2b9b2038a..55c079cf4 100644 --- a/trick_source/sim_services/DataRecord/DRBinary.cpp +++ b/trick_source/sim_services/DataRecord/DRBinary.cpp @@ -6,18 +6,20 @@ ((Alex Lin) (NASA) (April 2009) (--) (c++ port))) */ +#include "trick/DRBinary.hh" + +#include "trick/ReferenceUtils.hh" +#include "trick/bitfield_proto.h" +#include "trick/command_line_protos.h" +#include "trick/memorymanager_c_intf.h" + +#include #include #include #include -#include #include #include -#include "trick/DRBinary.hh" -#include "trick/command_line_protos.h" -#include "trick/memorymanager_c_intf.h" -#include "trick/bitfield_proto.h" - /* Other classes inherit from DRBinary. In these cases, we don't want to register the memory as DRBinary, so register_group will be set to false. @@ -110,10 +112,11 @@ int Trick::DRBinary::format_specific_init() { bytes += write( fd , rec_buffer[jj]->ref->attr->units , write_value ) ; } - write_value = rec_buffer[jj]->ref->attr->type ; + write_value = (int)Trick::ReferenceUtils::effective_trick_type(rec_buffer[jj]->ref); bytes += write( fd , &write_value , sizeof(int)) ; - bytes += write( fd , &rec_buffer[jj]->ref->attr->size , sizeof(int)) ; + write_value = (int)Trick::ReferenceUtils::effective_trick_size(rec_buffer[jj]->ref); + bytes += write(fd, &write_value, sizeof(int)); } total_bytes_written += bytes; return(0) ; @@ -136,45 +139,47 @@ int Trick::DRBinary::format_specific_write_data(unsigned int writer_offset) { /* Write out all parameters */ for (ii = 0; ii < rec_buffer.size() ; ii++) { - - address = rec_buffer[ii]->buffer + ( writer_offset * rec_buffer[ii]->ref->attr->size ) ; - - switch (rec_buffer[ii]->ref->attr->type) { - case TRICK_CHARACTER: - case TRICK_UNSIGNED_CHARACTER: - case TRICK_SHORT: - case TRICK_UNSIGNED_SHORT: - case TRICK_BOOLEAN: - case TRICK_ENUMERATED: - case TRICK_INTEGER: - case TRICK_UNSIGNED_INTEGER: - case TRICK_FLOAT: - case TRICK_LONG: - case TRICK_UNSIGNED_LONG: - case TRICK_LONG_LONG: - case TRICK_UNSIGNED_LONG_LONG: - case TRICK_STRUCTURED: - case TRICK_DOUBLE: - memcpy(writer_buff + len, address, (size_t)rec_buffer[ii]->ref->attr->size); - break; - - case TRICK_BITFIELD: - sbf = GET_BITFIELD(address, rec_buffer[ii]->ref->attr->size, - rec_buffer[ii]->ref->attr->index[0].start, rec_buffer[ii]->ref->attr->index[0].size); - memcpy(writer_buff + len, &sbf, (size_t)rec_buffer[ii]->ref->attr->size); - break; - - case TRICK_UNSIGNED_BITFIELD: - bf = GET_UNSIGNED_BITFIELD(address, rec_buffer[ii]->ref->attr->size, - rec_buffer[ii]->ref->attr->index[0].start, rec_buffer[ii]->ref->attr->index[0].size); - memcpy(writer_buff + len, &bf, (size_t)rec_buffer[ii]->ref->attr->size); - break; - - default: - break; + int item_size = (int)Trick::ReferenceUtils::effective_trick_size(rec_buffer[ii]->ref); + TRICK_TYPE item_type = Trick::ReferenceUtils::effective_trick_type(rec_buffer[ii]->ref); + address = rec_buffer[ii]->buffer + (writer_offset * item_size); + + switch (item_type) + { + case TRICK_CHARACTER: + case TRICK_UNSIGNED_CHARACTER: + case TRICK_SHORT: + case TRICK_UNSIGNED_SHORT: + case TRICK_BOOLEAN: + case TRICK_ENUMERATED: + case TRICK_INTEGER: + case TRICK_UNSIGNED_INTEGER: + case TRICK_FLOAT: + case TRICK_LONG: + case TRICK_UNSIGNED_LONG: + case TRICK_LONG_LONG: + case TRICK_UNSIGNED_LONG_LONG: + case TRICK_STRUCTURED: + case TRICK_DOUBLE: + memcpy(writer_buff + len, address, (size_t)item_size); + break; + + case TRICK_BITFIELD: + sbf = GET_BITFIELD(address, rec_buffer[ii]->ref->attr->size, rec_buffer[ii]->ref->attr->index[0].start, + rec_buffer[ii]->ref->attr->index[0].size); + memcpy(writer_buff + len, &sbf, (size_t)item_size); + break; + + case TRICK_UNSIGNED_BITFIELD: + bf = GET_UNSIGNED_BITFIELD(address, rec_buffer[ii]->ref->attr->size, + rec_buffer[ii]->ref->attr->index[0].start, + rec_buffer[ii]->ref->attr->index[0].size); + memcpy(writer_buff + len, &bf, (size_t)item_size); + break; + + default: + break; } - len += rec_buffer[ii]->ref->attr->size ; - + len += item_size; } return write( fd , writer_buff , len) ; diff --git a/trick_source/sim_services/DataRecord/DRHDF5.cpp b/trick_source/sim_services/DataRecord/DRHDF5.cpp index 24913b363..75060aa71 100644 --- a/trick_source/sim_services/DataRecord/DRHDF5.cpp +++ b/trick_source/sim_services/DataRecord/DRHDF5.cpp @@ -5,16 +5,18 @@ ((Warwick Woodard) (NASA) (February 2010) (--) (Initial version)) */ -#include -#include -#include - #include "trick/DRHDF5.hh" -#include "trick/parameter_types.h" + +#include "trick/ReferenceUtils.hh" +#include "trick/bitfield_proto.h" #include "trick/command_line_protos.h" #include "trick/memorymanager_c_intf.h" #include "trick/message_proto.h" -#include "trick/bitfield_proto.h" +#include "trick/parameter_types.h" + +#include +#include +#include Trick::DRHDF5::DRHDF5( std::string in_name, Trick::DR_Type dr_type ) : Trick::DataRecordGroup(in_name, dr_type) { register_group_with_mm(this, "Trick::DRHDF5") ; @@ -97,66 +99,77 @@ int Trick::DRHDF5::format_specific_init() { /* Case statements taken from "parameter_types.h." * HDF5 Native types found in "H5Tpublic.h." */ - switch (rec_buffer[ii]->ref->attr->type) { - case TRICK_CHARACTER: - datatype = H5T_NATIVE_CHAR; - break; - case TRICK_UNSIGNED_CHARACTER: - datatype = H5T_NATIVE_UCHAR; - break; - case TRICK_STRING: - datatype = s256; - break; - case TRICK_SHORT: - datatype = H5T_NATIVE_SHORT; - break; - case TRICK_UNSIGNED_SHORT: - datatype = H5T_NATIVE_USHORT; - break; - case TRICK_ENUMERATED: - case TRICK_INTEGER: + switch (Trick::ReferenceUtils::effective_trick_type(rec_buffer[ii]->ref)) + { + case TRICK_CHARACTER: + datatype = H5T_NATIVE_CHAR; + break; + case TRICK_UNSIGNED_CHARACTER: + datatype = H5T_NATIVE_UCHAR; + break; + case TRICK_STRING: + datatype = s256; + break; + case TRICK_SHORT: + datatype = H5T_NATIVE_SHORT; + break; + case TRICK_UNSIGNED_SHORT: + datatype = H5T_NATIVE_USHORT; + break; + case TRICK_ENUMERATED: + case TRICK_INTEGER: + datatype = H5T_NATIVE_INT; + break; + case TRICK_UNSIGNED_INTEGER: + datatype = H5T_NATIVE_UINT; + break; + case TRICK_LONG: + datatype = H5T_NATIVE_LONG; + break; + case TRICK_UNSIGNED_LONG: + datatype = H5T_NATIVE_ULONG; + break; + case TRICK_FLOAT: + datatype = H5T_NATIVE_FLOAT; + break; + case TRICK_DOUBLE: + datatype = H5T_NATIVE_DOUBLE; + break; + case TRICK_BITFIELD: + if (rec_buffer[ii]->ref->attr->size == sizeof(int)) + { datatype = H5T_NATIVE_INT; - break; - case TRICK_UNSIGNED_INTEGER: + } + else if (rec_buffer[ii]->ref->attr->size == sizeof(short)) + { + datatype = H5T_NATIVE_SHORT; + } + else + { + datatype = H5T_NATIVE_CHAR; + } + break; + case TRICK_UNSIGNED_BITFIELD: + if (rec_buffer[ii]->ref->attr->size == sizeof(unsigned int)) + { datatype = H5T_NATIVE_UINT; - break; - case TRICK_LONG: - datatype = H5T_NATIVE_LONG; - break; - case TRICK_UNSIGNED_LONG: - datatype = H5T_NATIVE_ULONG; - break; - case TRICK_FLOAT: - datatype = H5T_NATIVE_FLOAT; - break; - case TRICK_DOUBLE: - datatype = H5T_NATIVE_DOUBLE; - break; - case TRICK_BITFIELD: - if (rec_buffer[ii]->ref->attr->size == sizeof(int)) { - datatype = H5T_NATIVE_INT; - } else if (rec_buffer[ii]->ref->attr->size == sizeof(short)) { - datatype = H5T_NATIVE_SHORT; - } else { - datatype = H5T_NATIVE_CHAR; - } - break; - case TRICK_UNSIGNED_BITFIELD: - if (rec_buffer[ii]->ref->attr->size == sizeof(unsigned int)) { - datatype = H5T_NATIVE_UINT; - } else if (rec_buffer[ii]->ref->attr->size == sizeof(unsigned short)) { - datatype = H5T_NATIVE_USHORT; - } else { - datatype = H5T_NATIVE_UCHAR; - } - break; - case TRICK_LONG_LONG: - datatype = H5T_NATIVE_LLONG; - break; - case TRICK_UNSIGNED_LONG_LONG: - datatype = H5T_NATIVE_ULLONG; - break; - case TRICK_BOOLEAN: + } + else if (rec_buffer[ii]->ref->attr->size == sizeof(unsigned short)) + { + datatype = H5T_NATIVE_USHORT; + } + else + { + datatype = H5T_NATIVE_UCHAR; + } + break; + case TRICK_LONG_LONG: + datatype = H5T_NATIVE_LLONG; + break; + case TRICK_UNSIGNED_LONG_LONG: + datatype = H5T_NATIVE_ULLONG; + break; + case TRICK_BOOLEAN: #if ( __sun | __APPLE__ ) datatype = H5T_NATIVE_INT; #else @@ -165,7 +178,7 @@ int Trick::DRHDF5::format_specific_init() { break; default: continue; - } + } /* Create packet table(s) to store "fixed-length" packets. * A separate packet table (PT) is created for each variable. @@ -201,7 +214,8 @@ int Trick::DRHDF5::format_specific_init() { buf = "log_" + group_name ; H5PTappend( file_names_id, 1, buf.c_str() ); /* Param Type */ - buf = type_string(rec_buffer[ii]->ref->attr->type, rec_buffer[ii]->ref->attr->size ); + buf = type_string((int)Trick::ReferenceUtils::effective_trick_type(rec_buffer[ii]->ref), + (int)Trick::ReferenceUtils::effective_trick_size(rec_buffer[ii]->ref)); H5PTappend( param_types_id, 1, buf.c_str() ); /* Param Units */ if ( rec_buffer[ii]->ref->attr->mods & TRICK_MODS_UNITSDASHDASH ) { @@ -233,87 +247,101 @@ void append_var_packet_table(Trick::DataRecordBuffer *drb, char* buf, size_t rec void* data = 0; int bf; - switch (drb->ref->attr->type) { - case TRICK_CHARACTER: - case TRICK_UNSIGNED_CHARACTER: - case TRICK_STRING: - case TRICK_SHORT: - case TRICK_UNSIGNED_SHORT: - case TRICK_ENUMERATED: - case TRICK_INTEGER: - case TRICK_UNSIGNED_INTEGER: - case TRICK_LONG: - case TRICK_UNSIGNED_LONG: - case TRICK_FLOAT: - case TRICK_DOUBLE: - H5PTappend(param_ds, records , buf); - break; - case TRICK_BITFIELD: - bf = GET_BITFIELD(buf, drb->ref->attr->size, drb->ref->attr->index[0].start, drb->ref->attr->index[0].size); - data = malloc(records * sizeof(bf)); - - // Extract bitfield for each record from different segments of buf - for (size_t j = 0; j < records; j++) { - // Calculate the correct offset in buf for each record - // Each record in buf has size of rec_buffer[ii]->ref->attr->size - size_t offset = j * drb->ref->attr->size; - - if (drb->ref->attr->size == sizeof(int)) { - ((int *)data)[j] = extract_bitfield_any( - *(int *)(buf+offset), drb->ref->attr->size, - drb->ref->attr->index[0].start, drb->ref->attr->index[0].size); - } else if (drb->ref->attr->size == sizeof(short)) { - ((short *)data)[j] = extract_bitfield_any( - *(short *)(buf+offset), drb->ref->attr->size, - drb->ref->attr->index[0].start, drb->ref->attr->index[0].size); - } else if (drb->ref->attr->size == sizeof(char)) { - ((char *)data)[j] = extract_bitfield_any( - *(char *)(buf+offset), drb->ref->attr->size, - drb->ref->attr->index[0].start, drb->ref->attr->index[0].size); - } else { - ((int*)data)[j] = extract_bitfield_any( - *(int *)(buf+offset), drb->ref->attr->size, - drb->ref->attr->index[0].start, drb->ref->attr->index[0].size); - } + switch (Trick::ReferenceUtils::effective_trick_type(drb->ref)) + { + case TRICK_CHARACTER: + case TRICK_UNSIGNED_CHARACTER: + case TRICK_STRING: + case TRICK_SHORT: + case TRICK_UNSIGNED_SHORT: + case TRICK_ENUMERATED: + case TRICK_INTEGER: + case TRICK_UNSIGNED_INTEGER: + case TRICK_LONG: + case TRICK_UNSIGNED_LONG: + case TRICK_FLOAT: + case TRICK_DOUBLE: + H5PTappend(param_ds, records, buf); + break; + case TRICK_BITFIELD: + bf = GET_BITFIELD(buf, drb->ref->attr->size, drb->ref->attr->index[0].start, drb->ref->attr->index[0].size); + data = malloc(records * sizeof(bf)); + + // Extract bitfield for each record from different segments of buf + for (size_t j = 0; j < records; j++) + { + // Calculate the correct offset in buf for each record + // Each record in buf has size of rec_buffer[ii]->ref->attr->size + size_t offset = j * drb->ref->attr->size; + + if (drb->ref->attr->size == sizeof(int)) + { + ((int*)data)[j] = extract_bitfield_any(*(int*)(buf + offset), drb->ref->attr->size, + drb->ref->attr->index[0].start, drb->ref->attr->index[0].size); } - H5PTappend(param_ds, records, data); - break; - case TRICK_UNSIGNED_BITFIELD: - bf = GET_UNSIGNED_BITFIELD(buf, drb->ref->attr->size, drb->ref->attr->index[0].start, drb->ref->attr->index[0].size); - data = malloc(records * sizeof(bf)); - - // Extract bitfield for each record from different segments of buf - for (size_t j = 0; j < records; j++) { - // Calculate the correct offset in buf for each record - // Each record in buf has size of rec_buffer[ii]->ref->attr->size - size_t offset = j * drb->ref->attr->size; // record_size would be the size of one record in buf - - if (drb->ref->attr->size == sizeof(int)) { - ((unsigned int *)data)[j] = extract_unsigned_bitfield_any( - *(unsigned int *)(buf+offset), drb->ref->attr->size, + else if (drb->ref->attr->size == sizeof(short)) + { + ((short*)data)[j] = extract_bitfield_any(*(short*)(buf + offset), drb->ref->attr->size, + drb->ref->attr->index[0].start, drb->ref->attr->index[0].size); + } + else if (drb->ref->attr->size == sizeof(char)) + { + ((char*)data)[j] = extract_bitfield_any(*(char*)(buf + offset), drb->ref->attr->size, + drb->ref->attr->index[0].start, drb->ref->attr->index[0].size); + } + else + { + ((int*)data)[j] = extract_bitfield_any(*(int*)(buf + offset), drb->ref->attr->size, + drb->ref->attr->index[0].start, drb->ref->attr->index[0].size); + } + } + H5PTappend(param_ds, records, data); + break; + case TRICK_UNSIGNED_BITFIELD: + bf = GET_UNSIGNED_BITFIELD(buf, drb->ref->attr->size, drb->ref->attr->index[0].start, + drb->ref->attr->index[0].size); + data = malloc(records * sizeof(bf)); + + // Extract bitfield for each record from different segments of buf + for (size_t j = 0; j < records; j++) + { + // Calculate the correct offset in buf for each record + // Each record in buf has size of rec_buffer[ii]->ref->attr->size + size_t offset = j * drb->ref->attr->size; // record_size would be the size of one record in buf + + if (drb->ref->attr->size == sizeof(int)) + { + ((unsigned int*)data)[j] + = extract_unsigned_bitfield_any(*(unsigned int*)(buf + offset), drb->ref->attr->size, drb->ref->attr->index[0].start, drb->ref->attr->index[0].size); - } else if (drb->ref->attr->size == sizeof(short)) { - ((unsigned short *)data)[j] = extract_unsigned_bitfield_any( - *(unsigned short *)(buf+offset), drb->ref->attr->size, + } + else if (drb->ref->attr->size == sizeof(short)) + { + ((unsigned short*)data)[j] + = extract_unsigned_bitfield_any(*(unsigned short*)(buf + offset), drb->ref->attr->size, drb->ref->attr->index[0].start, drb->ref->attr->index[0].size); - } else if (drb->ref->attr->size == sizeof(char)) { - ((unsigned char *)data)[j] = extract_unsigned_bitfield_any( - *(unsigned char *)(buf+offset), drb->ref->attr->size, + } + else if (drb->ref->attr->size == sizeof(char)) + { + ((unsigned char*)data)[j] + = extract_unsigned_bitfield_any(*(unsigned char*)(buf + offset), drb->ref->attr->size, drb->ref->attr->index[0].start, drb->ref->attr->index[0].size); - } else { - ((int *)data)[j] = extract_unsigned_bitfield_any( - *(int *)(buf+offset), drb->ref->attr->size, + } + else + { + ((int*)data)[j] + = extract_unsigned_bitfield_any(*(int*)(buf + offset), drb->ref->attr->size, drb->ref->attr->index[0].start, drb->ref->attr->index[0].size); - } } - H5PTappend(param_ds, records, data); - break; - case TRICK_LONG_LONG: - case TRICK_UNSIGNED_LONG_LONG: - case TRICK_BOOLEAN: - default: - H5PTappend(param_ds, records , buf); - break; + } + H5PTappend(param_ds, records, data); + break; + case TRICK_LONG_LONG: + case TRICK_UNSIGNED_LONG_LONG: + case TRICK_BOOLEAN: + default: + H5PTappend(param_ds, records, buf); + break; if (data != 0) { free(data); diff --git a/trick_source/sim_services/DataRecord/DataRecordGroup.cpp b/trick_source/sim_services/DataRecord/DataRecordGroup.cpp index b49b3da6b..453bd3ad2 100644 --- a/trick_source/sim_services/DataRecord/DataRecordGroup.cpp +++ b/trick_source/sim_services/DataRecord/DataRecordGroup.cpp @@ -13,12 +13,13 @@ #endif #include "trick/DataRecordGroup.hh" +#include "trick/ReferenceUtils.hh" #include "trick/command_line_protos.h" #include "trick/exec_proto.h" -#include "trick/reference.h" #include "trick/memorymanager_c_intf.h" #include "trick/message_proto.h" #include "trick/message_type.h" +#include "trick/reference.h" /** @details @@ -361,13 +362,29 @@ int Trick::DataRecordGroup::add_change_variable( std::string in_name ) { } bool Trick::DataRecordGroup::isSupportedType(REF2 * ref2, std::string& message) { - if (ref2->attr->type == TRICK_STRING || ref2->attr->type == TRICK_STL || ref2->attr->type == TRICK_STRUCTURED) { - message = "Cannot Data Record variable " + std::string(ref2->reference) + " of unsupported type " + std::to_string(ref2->attr->type); + // For STL-indexed paths the effective type is the element/member type, not TRICK_STL. + TRICK_TYPE eff_type = Trick::ReferenceUtils::effective_trick_type(ref2); + + // Reject bare (unindexed) STL containers — user must index, e.g. vec[0] + if (ref2->attr->type == TRICK_STL && !Trick::ReferenceUtils::is_stl_ref(ref2)) + { + message = "Cannot Data Record bare STL container " + std::string(ref2->reference) + + " (use indexed access, e.g. " + std::string(ref2->reference) + "[0])"; return false; } - - // If this is an array and not a single value, don't record it - if (ref2->num_index != ref2->attr->num_index) { + + if (eff_type == TRICK_STRING || eff_type == TRICK_WSTRING || eff_type == TRICK_STL || eff_type == TRICK_STRUCTURED + || eff_type == TRICK_NUMBER_OF_TYPES) + { + message = "Cannot Data Record variable " + std::string(ref2->reference) + " of unsupported type " + + std::to_string(eff_type); + return false; + } + + // For STL-present paths skip the array dimension check — num_index/attr->num_index + // semantics do not apply when an STL container was indexed anywhere in the path. + if (!Trick::ReferenceUtils::is_stl_ref(ref2) && ref2->num_index != ref2->attr->num_index) + { message = "Cannot Data Record arrayed variable " + std::string(ref2->reference); return false; } @@ -430,8 +447,9 @@ int Trick::DataRecordGroup::init(bool is_restart) { if ( drb->alias.compare("") ) { drb->ref->reference = strdup(drb->alias.c_str()) ; } - drb->last_value = (char *)calloc(1 , drb->ref->attr->size) ; - drb->buffer = (char *)calloc(max_num , drb->ref->attr->size) ; + size_t elem_size = Trick::ReferenceUtils::effective_trick_size(drb->ref); + drb->last_value = (char*)calloc(1, elem_size); + drb->buffer = (char*)calloc(max_num, elem_size); drb->ref_searched = true ; } @@ -666,9 +684,9 @@ int Trick::DataRecordGroup::write_header() { for (jj = 0; jj < rec_buffer.size() ; jj++) { /*! recording single data item */ out_stream << "log_" << group_name << "\t" - << type_string(rec_buffer[jj]->ref->attr->type, - rec_buffer[jj]->ref->attr->size) << "\t" - << std::setw(6) ; + << type_string((int)Trick::ReferenceUtils::effective_trick_type(rec_buffer[jj]->ref), + (int)Trick::ReferenceUtils::effective_trick_size(rec_buffer[jj]->ref)) + << "\t" << std::setw(6); if ( rec_buffer[jj]->ref->attr->mods & TRICK_MODS_UNITSDASHDASH ) { out_stream << "--" ; @@ -731,7 +749,7 @@ int Trick::DataRecordGroup::data_record(double in_time) { for (jj = 0; jj < rec_buffer.size() ; jj++) { drb = rec_buffer[jj] ; REF2 * ref = drb->ref ; - int param_size = ref->attr->size ; + int param_size = (int)Trick::ReferenceUtils::effective_trick_size(ref); if ( buffer_offset == 0 ) { drb->curr_buffer = drb->buffer ; } else { @@ -762,10 +780,11 @@ int Trick::DataRecordGroup::data_record(double in_time) { for (jj = 0; jj < rec_buffer.size() ; jj++) { drb = rec_buffer[jj] ; REF2 * ref = drb->ref ; - if ( ref->pointer_present == 1 ) { + if (ref->pointer_present == 1 && !Trick::ReferenceUtils::is_stl_ref(ref)) + { ref->address = follow_address_path(ref) ; } - int param_size = ref->attr->size ; + int param_size = (int)Trick::ReferenceUtils::effective_trick_size(ref); if ( buffer_offset == 0 ) { drb->curr_buffer = drb->buffer ; } else { diff --git a/trick_source/sim_services/MemoryManager/ReferenceUtils.cpp b/trick_source/sim_services/MemoryManager/ReferenceUtils.cpp new file mode 100644 index 000000000..7e9ddd3c3 --- /dev/null +++ b/trick_source/sim_services/MemoryManager/ReferenceUtils.cpp @@ -0,0 +1,87 @@ +#include "trick/ReferenceUtils.hh" + +#include + +// Returns the size in bytes of the element type for an STL container. +// For example, for a std::vector, it would return sizeof(int). +static size_t stl_elem_type_size(TRICK_TYPE elem_type) +{ + switch (elem_type) + { + case TRICK_CHARACTER: + case TRICK_UNSIGNED_CHARACTER: + case TRICK_BOOLEAN: + return sizeof(char); + case TRICK_SHORT: + case TRICK_UNSIGNED_SHORT: + return sizeof(short); + case TRICK_INTEGER: + case TRICK_UNSIGNED_INTEGER: + case TRICK_ENUMERATED: + return sizeof(int); + case TRICK_LONG: + case TRICK_UNSIGNED_LONG: + return sizeof(long); + case TRICK_LONG_LONG: + case TRICK_UNSIGNED_LONG_LONG: + return sizeof(long long); + case TRICK_FLOAT: + return sizeof(float); + case TRICK_DOUBLE: + return sizeof(double); + case TRICK_STRING: + case TRICK_WSTRING: + case TRICK_STRUCTURED: + return sizeof(void*); + default: + return 0; + } +} + +// Check if a reference is to an STL container element. +// Returns true if the reference points to an element within an STL container, false otherwise. +bool Trick::ReferenceUtils::is_stl_ref(const REF2* ref) +{ + if (!ref || !ref->attr) + return false; + if (ref->stl_present == 1) + return true; + if (ref->attr->type == TRICK_STL && ref->reference) + { + size_t len = strlen(ref->reference); + return (len > 0 && ref->reference[len - 1] == ']'); + } + return false; +} + +// Determine the effective Trick type of a reference. +// If the reference points to an element within an STL container, return the element type. +// Otherwise, return the type of the attribute itself. +TRICK_TYPE Trick::ReferenceUtils::effective_trick_type(const REF2* ref) +{ + if (!ref || !ref->attr) + return TRICK_NUMBER_OF_TYPES; + if (ref->attr->type == TRICK_STL && ref->reference) + { + size_t len = strlen(ref->reference); + if (len > 0 && ref->reference[len - 1] == ']') + return ref->attr->stl_elem_type; + } + return ref->attr->type; +} + +// Determine the effective size of a reference. +// If the reference points to an element within an STL container, return the size of the element type. +// Otherwise, return the size of the attribute itself. +size_t Trick::ReferenceUtils::effective_trick_size(const REF2* ref) +{ + if (!ref || !ref->attr) + return 0; + if (ref->attr->type == TRICK_STL && ref->reference) + { + size_t len = strlen(ref->reference); + if (len > 0 && ref->reference[len - 1] == ']') + return stl_elem_type_size(ref->attr->stl_elem_type); + } + return (size_t)ref->attr->size; +} diff --git a/trick_source/sim_services/VariableServer/VariableReference.cpp b/trick_source/sim_services/VariableServer/VariableReference.cpp index 478306b7b..626eb5940 100644 --- a/trick_source/sim_services/VariableServer/VariableReference.cpp +++ b/trick_source/sim_services/VariableServer/VariableReference.cpp @@ -1,21 +1,22 @@ -#include -#include -#include -#include // for fpclassify -#include // for setprecision -#include -#include - #include "trick/VariableReference.hh" -#include "trick/memorymanager_c_intf.h" -#include "trick/wcs_ext.h" + +#include "trick/ReferenceUtils.hh" +#include "trick/UdUnits.hh" +#include "trick/bitfield_proto.h" #include "trick/map_trick_units_to_udunits.hh" +#include "trick/memorymanager_c_intf.h" #include "trick/message_proto.h" #include "trick/message_type.h" -#include "trick/UdUnits.hh" -#include "trick/bitfield_proto.h" #include "trick/trick_byteswap.h" +#include "trick/wcs_ext.h" +#include // for setprecision +#include +#include // for fpclassify +#include +#include +#include +#include // Static variables to be addresses that are known to be the error ref address int Trick::VariableReference::_bad_ref_int = 0 ; @@ -123,87 +124,20 @@ Trick::VariableReference::VariableReference(std::string var_name) : _staged(fals _size = _var_info->attr->size ; _deref = false; - // Deal with weirdness around string vs wstring - _trick_type = _var_info->attr->type ; - - // Special handling for indexed STL containers (e.g., vec[0], point_vec[0].x) - // We need to detect two cases: - // 1. Final attr is TRICK_STL AND we indexed it (e.g., vec[0]) - update type/size to element - // 2. Pattern "]." in reference - we indexed something then accessed a member (e.g., point_vec[0].x) - // - // For case 1, we need to update _trick_type and _size to match the element type. - // For case 2, the final attr is already the member's attributes (e.g., double x), so _trick_type - // and _size are already correct - we just need to set the flag to skip follow_address_path(). - // - // Important: If reference is just "vec" (no indexing), keep it as TRICK_STL container type. - _used_stl_indexing = false; - if ( _var_info->attr->type == TRICK_STL && _var_info->reference ) { - // Check if the STL container was actually indexed by checking if reference ends with ']' - // e.g., "vec[0]" ends with ']', but "vec" or "xxx[0].vec" do not - size_t len = strlen(_var_info->reference); - bool stl_was_indexed = (len > 0 && _var_info->reference[len - 1] == ']'); - - if (stl_was_indexed) { - // Case 1: Final attr is STL container AND we indexed it (e.g., vec[0]) - // Update type and size to match the element, not the container - _trick_type = _var_info->attr->stl_elem_type; - _used_stl_indexing = true; - - // Update _size to match the element type size, not the container size - switch (_trick_type) { - case TRICK_CHARACTER: - case TRICK_UNSIGNED_CHARACTER: - case TRICK_BOOLEAN: - _size = sizeof(char); - break; - case TRICK_SHORT: - case TRICK_UNSIGNED_SHORT: - _size = sizeof(short); - break; - case TRICK_INTEGER: - case TRICK_UNSIGNED_INTEGER: - case TRICK_ENUMERATED: - _size = sizeof(int); - break; - case TRICK_LONG: - case TRICK_UNSIGNED_LONG: - _size = sizeof(long); - break; - case TRICK_LONG_LONG: - case TRICK_UNSIGNED_LONG_LONG: - _size = sizeof(long long); - break; - case TRICK_FLOAT: - _size = sizeof(float); - break; - case TRICK_DOUBLE: - _size = sizeof(double); - break; - case TRICK_STRING: - case TRICK_WSTRING: - case TRICK_STRUCTURED: - _size = sizeof(void*); - break; - default: - // Keep existing size for unknown types - break; - } - - // address already points to the element from ref_dim - // Treat as single value - nothing else necessary - } - } else { - // Case 2: Not a directly indexed STL container - // Handle mixed STL+pointer cases or regular array size calculations - - // Check for STL indexing - set flag to skip follow_address_path call - // For mixed STL+pointer cases, this ensures follow_address_path is skipped - // For STL-only cases (no pointers), this flag doesn't change behavior since - // follow_address_path is only called when pointer_present == 1 - if ( _var_info->stl_present == 1 ) { - _used_stl_indexing = true; - } + // Use ReferenceUtils for STL-aware type and size resolution. + // Handles cases such as: vec[0], xxx[2].yyy.zzz[3].www, xxx[2].yyy.zzz[3].aaa[0] + _trick_type = Trick::ReferenceUtils::effective_trick_type(_var_info); + _used_stl_indexing = Trick::ReferenceUtils::is_stl_ref(_var_info); + if (_used_stl_indexing) + { + // effective_trick_size returns the correct element byte size for every STL case + _size = (int)Trick::ReferenceUtils::effective_trick_size(_var_info); + // address already points to the correct element from ref_dim; treat as single value + } + else + { + // Non-STL: apply the original array dimension size calculation if ( _var_info->num_index == _var_info->attr->num_index ) { // single value - nothing else necessary } else if ( _var_info->attr->index[_var_info->attr->num_index - 1].size != 0 ) { From a005f116a52c407e626103bcff54ab6ab08b9bc5 Mon Sep 17 00:00:00 2001 From: Hong Chen Date: Tue, 23 Jun 2026 09:24:41 -0500 Subject: [PATCH 2/5] ruff check python code and add missing ref log file. --- .../Ref_Logs/log_STL_DR_hdf5_Master.header | 18 ++++++++++++++++++ test/SIM_stls/RUN_test_dr/input_dr.py | 6 ++++-- 2 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 test/SIM_stls/RUN_test_dr/Ref_Logs/log_STL_DR_hdf5_Master.header diff --git a/test/SIM_stls/RUN_test_dr/Ref_Logs/log_STL_DR_hdf5_Master.header b/test/SIM_stls/RUN_test_dr/Ref_Logs/log_STL_DR_hdf5_Master.header new file mode 100644 index 000000000..97d053da3 --- /dev/null +++ b/test/SIM_stls/RUN_test_dr/Ref_Logs/log_STL_DR_hdf5_Master.header @@ -0,0 +1,18 @@ +log_STL_DR_hdf5 byte_order is HDF5 +log_STL_DR_hdf5 double s sys.exec.out.time +log_STL_DR_hdf5 double 1 the_object.stlc.double_vector[0] +log_STL_DR_hdf5 double 1 the_object.stlc.double_vector[1] +log_STL_DR_hdf5 double 1 the_object.stlc.double_vector[2] +log_STL_DR_hdf5 float 1 the_object.stlc.float_deque[0] +log_STL_DR_hdf5 float 1 the_object.stlc.float_deque[1] +log_STL_DR_hdf5 float 1 the_object.stlc.float_deque[2] +log_STL_DR_hdf5 int 1 the_object.stlc.int_array[0] +log_STL_DR_hdf5 int 1 the_object.stlc.int_array[1] +log_STL_DR_hdf5 int 1 the_object.stlc.int_array[2] +log_STL_DR_hdf5 int 1 the_object.stlc.int_array[3] +log_STL_DR_hdf5 long_long 1 the_object.stlc.vec_user_simple[0].b +log_STL_DR_hdf5 int 1 the_object.stlc.vec_user_simple[0].a[0] +log_STL_DR_hdf5 int 1 the_object.stlc.vec_user_simple[0].a[2] +log_STL_DR_hdf5 int 1 the_object.stlc.vec_user_defined[0].a +log_STL_DR_hdf5 int 1 the_object.stlc.vec_user_defined[0].vec[0] +log_STL_DR_hdf5 int 1 the_object.stlc.vec_user_defined[0].vec[2] diff --git a/test/SIM_stls/RUN_test_dr/input_dr.py b/test/SIM_stls/RUN_test_dr/input_dr.py index 7583d3b3c..93d8836c2 100644 --- a/test/SIM_stls/RUN_test_dr/input_dr.py +++ b/test/SIM_stls/RUN_test_dr/input_dr.py @@ -1,9 +1,10 @@ import trick + def main(): trick.exec_set_job_onoff("the_object.stlc.addData", 1, True) - trick.exec_set_job_onoff("the_object.stlc.test", 1, False) - trick.exec_set_job_onoff("the_object.stlc.print", 1, False) + trick.exec_set_job_onoff("the_object.stlc.test", 1, False) + trick.exec_set_job_onoff("the_object.stlc.print", 1, False) # --------------------------------------------------------------- # ASCII data recording group for STL primitive containers @@ -99,5 +100,6 @@ def main(): trick.exec_set_freeze_frame(0.10) trick.stop(1.0) + if __name__ == "__main__": main() From 4f30155799c80aa002c88046763832a2bd901a8f Mon Sep 17 00:00:00 2001 From: Hong Chen Date: Tue, 23 Jun 2026 12:06:55 -0500 Subject: [PATCH 3/5] Add guard for hdf5 recording and comparison, also added ref log h5 file. --- .../Ref_Logs/log_STL_DR_hdf5_Master.h5 | Bin 0 -> 63353 bytes test/SIM_stls/RUN_test_dr/input_dr.py | 13 +++++++++---- test_sims.yml | 1 - 3 files changed, 9 insertions(+), 5 deletions(-) create mode 100644 test/SIM_stls/RUN_test_dr/Ref_Logs/log_STL_DR_hdf5_Master.h5 diff --git a/test/SIM_stls/RUN_test_dr/Ref_Logs/log_STL_DR_hdf5_Master.h5 b/test/SIM_stls/RUN_test_dr/Ref_Logs/log_STL_DR_hdf5_Master.h5 new file mode 100644 index 0000000000000000000000000000000000000000..f77f042ac577efc7274c236e26fc0f8f87806431 GIT binary patch literal 63353 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 Date: Tue, 23 Jun 2026 12:12:30 -0500 Subject: [PATCH 4/5] ruff check python --- test/SIM_stls/RUN_test_dr/input_dr.py | 2 +- test_sims.yml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/test/SIM_stls/RUN_test_dr/input_dr.py b/test/SIM_stls/RUN_test_dr/input_dr.py index d7427a377..a023347ac 100644 --- a/test/SIM_stls/RUN_test_dr/input_dr.py +++ b/test/SIM_stls/RUN_test_dr/input_dr.py @@ -1,7 +1,7 @@ import trick has_dhf5 = False -if hasattr(trick, 'DRHDF5'): +if hasattr(trick, "DRHDF5"): has_dhf5 = True diff --git a/test_sims.yml b/test_sims.yml index 235355cc1..c3ab0fe60 100644 --- a/test_sims.yml +++ b/test_sims.yml @@ -253,6 +253,7 @@ SIM_stls: compare: - test/SIM_stls/RUN_test_dr/log_STL_DR.csv vs. test/SIM_stls/RUN_test_dr/Ref_Logs/log_STL_DR_Master.csv - test/SIM_stls/RUN_test_dr/log_STL_DR_bin.trk vs. test/SIM_stls/RUN_test_dr/Ref_Logs/log_STL_DR_bin_Master.trk + analyze: "test ! -f test/SIM_stls/RUN_test_dr/log_STL_DR_hdf5.header || diff test/SIM_stls/RUN_test_dr/log_STL_DR_hdf5.header test/SIM_stls/RUN_test_dr/Ref_Logs/log_STL_DR_hdf5_Master.header" SIM_test_dr: path: test/SIM_test_dr From 758ea05ad9f08a45b4d1738c24afcefb7bd8766d Mon Sep 17 00:00:00 2001 From: Hong Chen Date: Tue, 23 Jun 2026 15:31:06 -0500 Subject: [PATCH 5/5] Fixed unreachable code. --- trick_source/sim_services/DataRecord/DRHDF5.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/trick_source/sim_services/DataRecord/DRHDF5.cpp b/trick_source/sim_services/DataRecord/DRHDF5.cpp index 75060aa71..b6bf0dc39 100644 --- a/trick_source/sim_services/DataRecord/DRHDF5.cpp +++ b/trick_source/sim_services/DataRecord/DRHDF5.cpp @@ -342,11 +342,10 @@ void append_var_packet_table(Trick::DataRecordBuffer *drb, char* buf, size_t rec default: H5PTappend(param_ds, records, buf); break; - - if (data != 0) { - free(data); - data = 0; - } + } + if (data != 0) + { + free(data); } } #endif