diff --git a/Makefile b/Makefile index 1041f54..4494535 100644 --- a/Makefile +++ b/Makefile @@ -26,7 +26,7 @@ DSE_SCHEMA_VERSION ?= 1.2.8 export DSE_SCHEMA_URL ?= $(DSE_SCHEMA_REPO)/releases/download/v$(DSE_SCHEMA_VERSION)/dse-schemas.tar.gz DSE_NCODEC_REPO ?= https://github.com/boschglobal/dse.standards -DSE_NCODEC_VERSION ?= 1.0.7 +DSE_NCODEC_VERSION ?= 1.0.8 export DSE_NCODEC_URL ?= $(DSE_NCODEC_REPO)/archive/refs/tags/v$(DSE_NCODEC_VERSION).zip diff --git a/doc/content/apis/modelc/examples/model_create.c b/doc/content/apis/modelc/examples/model_create.c index 715e53c..ef4a1ee 100644 --- a/doc/content/apis/modelc/examples/model_create.c +++ b/doc/content/apis/modelc/examples/model_create.c @@ -13,7 +13,7 @@ typedef struct { static inline double* _index(ExtendedModelDesc* m, const char* v, const char* s) { - ModelSignalIndex idx = m->model.index((ModelDesc*)m, v, s); + ModelSignalIndex idx = signal_index((ModelDesc*)m, v, s); if (idx.scalar == NULL) log_fatal("Signal not found (%s:%s)", v, s); return idx.scalar; } diff --git a/dse/mocks/simmock.c b/dse/mocks/simmock.c index 913c1c0..0f7504f 100644 --- a/dse/mocks/simmock.c +++ b/dse/mocks/simmock.c @@ -216,7 +216,7 @@ void simmock_load(SimMock* mock) void* handle = dlopen( model->mi->model_definition.full_path, RTLD_NOW | RTLD_LOCAL); - if (handle == NULL) log_notice("ERROR: dlopen call: %s", dlerror()); + if (handle == NULL) log_error("ERROR: dlopen call: %s", dlerror()); assert_non_null(handle); model->vtable.create = dlsym(handle, MODEL_CREATE_FUNC_NAME); model->vtable.step = dlsym(handle, MODEL_STEP_FUNC_NAME); diff --git a/dse/modelc/examples/binary/model.c b/dse/modelc/examples/binary/model.c index 942379b..1037f15 100644 --- a/dse/modelc/examples/binary/model.c +++ b/dse/modelc/examples/binary/model.c @@ -12,7 +12,7 @@ typedef struct { SignalVector* sv; uint32_t index; - char* buffer; + uint8_t* buffer; uint32_t buffer_size; } BinarySignalDesc; @@ -32,7 +32,7 @@ typedef struct { static inline double* _index_scalar( ExtendedModelDesc* m, const char* v, const char* s) { - ModelSignalIndex idx = m->model.index((ModelDesc*)m, v, s); + ModelSignalIndex idx = signal_index((ModelDesc*)m, v, s); if (idx.scalar == NULL) log_fatal("Signal not found (%s:%s)", v, s); return idx.scalar; } @@ -41,7 +41,7 @@ static inline double* _index_scalar( static inline BinarySignalDesc _index_binary( ExtendedModelDesc* m, const char* v, const char* s) { - ModelSignalIndex idx = m->model.index((ModelDesc*)m, v, s); + ModelSignalIndex idx = signal_index((ModelDesc*)m, v, s); if (idx.binary == NULL) log_fatal("Signal not found (%s:%s)", v, s); BinarySignalDesc ret = { @@ -74,7 +74,7 @@ ModelDesc* model_create(ModelDesc* model) static inline int _format_message(BinarySignalDesc* b, int v) { - return snprintf(b->buffer, b->buffer_size, "count is %d", v); + return snprintf((char*)b->buffer, b->buffer_size, "count is %d", v); } int model_step(ModelDesc* model, double* model_time, double stop_time) @@ -82,22 +82,24 @@ int model_step(ModelDesc* model, double* model_time, double stop_time) ExtendedModelDesc* m = (ExtendedModelDesc*)model; /* Print the binary signal. */ + uint8_t* buffer; + size_t len; + signal_read(m->binary.message.sv, m->binary.message.index, &buffer, &len); log_info("Message (%s) : %s", - m->binary.message.sv->signal[m->binary.message.index], - m->binary.message.sv->binary[m->binary.message.index]); + m->binary.message.sv->signal[m->binary.message.index], buffer); /* Scalar signals. */ *(m->scalars.counter) += 1; /* Binary signals. */ - int len = _format_message(&(m->binary.message), (int)*(m->scalars.counter)); - if (len >= (int)(m->binary.message.buffer_size - 1)) { + len = _format_message(&(m->binary.message), (int)*(m->scalars.counter)); + if (len >= (m->binary.message.buffer_size - 1)) { m->binary.message.buffer = realloc(m->binary.message.buffer, len + 1); m->binary.message.buffer_size = len + 1; _format_message(&(m->binary.message), (int)*(m->scalars.counter)); } signal_reset(m->binary.message.sv, m->binary.message.index); signal_append(m->binary.message.sv, m->binary.message.index, - m->binary.message.buffer, strlen(m->binary.message.buffer) + 1); + m->binary.message.buffer, strlen((char*)m->binary.message.buffer) + 1); *model_time = stop_time; return 0; diff --git a/dse/modelc/examples/doc/apis/model_create.c b/dse/modelc/examples/doc/apis/model_create.c index 715e53c..ef4a1ee 100644 --- a/dse/modelc/examples/doc/apis/model_create.c +++ b/dse/modelc/examples/doc/apis/model_create.c @@ -13,7 +13,7 @@ typedef struct { static inline double* _index(ExtendedModelDesc* m, const char* v, const char* s) { - ModelSignalIndex idx = m->model.index((ModelDesc*)m, v, s); + ModelSignalIndex idx = signal_index((ModelDesc*)m, v, s); if (idx.scalar == NULL) log_fatal("Signal not found (%s:%s)", v, s); return idx.scalar; } diff --git a/dse/modelc/examples/extended/model.c b/dse/modelc/examples/extended/model.c index ebe14f0..4d9a2b7 100644 --- a/dse/modelc/examples/extended/model.c +++ b/dse/modelc/examples/extended/model.c @@ -22,7 +22,7 @@ typedef struct { static inline double* _index(ExtendedModelDesc* m, const char* v, const char* s) { - ModelSignalIndex idx = m->model.index((ModelDesc*)m, v, s); + ModelSignalIndex idx = signal_index((ModelDesc*)m, v, s); if (idx.scalar == NULL) log_fatal("Signal not found (%s:%s)", v, s); return idx.scalar; } diff --git a/dse/modelc/examples/gateway/gateway.c b/dse/modelc/examples/gateway/gateway.c index 0921b4f..e909351 100644 --- a/dse/modelc/examples/gateway/gateway.c +++ b/dse/modelc/examples/gateway/gateway.c @@ -57,11 +57,11 @@ int main(int argc, char** argv) sv->name, i, sv->length[i], sv->buffer_size[i], sv->binary[i], sv->signal[i]); /* Exchange/update the gateway signal. */ - char buffer[100]; - snprintf(buffer, sizeof(buffer), "st=%f,index=%d", + uint8_t buffer[100]; + snprintf((char*)buffer, sizeof(buffer), "st=%f,index=%d", model_time, i); signal_reset(sv, i); - signal_append(sv, i, buffer, strlen(buffer) + 1); + signal_append(sv, i, buffer, strlen((char*)buffer) + 1); } } else { /* Scalar vector. */ diff --git a/dse/modelc/examples/ncodec/model.c b/dse/modelc/examples/ncodec/model.c index 33687ac..fbd3ca3 100644 --- a/dse/modelc/examples/ncodec/model.c +++ b/dse/modelc/examples/ncodec/model.c @@ -20,7 +20,7 @@ typedef struct { static inline NCODEC* _index(ExtendedModelDesc* m, const char* v, const char* s) { - ModelSignalIndex idx = m->model.index((ModelDesc*)m, v, s); + ModelSignalIndex idx = signal_index((ModelDesc*)m, v, s); if (idx.binary == NULL) log_fatal("Signal not found (%s:%s)", v, s); NCODEC* nc = signal_codec(idx.sv, idx.signal); diff --git a/dse/modelc/examples/runtime/sim/model.c b/dse/modelc/examples/runtime/sim/model.c index cfc6656..7227040 100644 --- a/dse/modelc/examples/runtime/sim/model.c +++ b/dse/modelc/examples/runtime/sim/model.c @@ -22,10 +22,10 @@ typedef struct { static inline NCODEC* _index(ExtendedModelDesc* m, const char* v, const char* s) { - ModelSignalIndex idx = m->model.index((ModelDesc*)m, v, s); + ModelSignalIndex idx = signal_index((ModelDesc*)m, v, s); if (idx.binary == NULL) log_fatal("Signal not found (%s:%s)", v, s); - NCODEC* nc = idx.sv->codec(idx.sv, idx.signal); + NCODEC* nc = signal_codec(idx.sv, idx.signal); if (nc == NULL) log_fatal("NCodec object not available (%s:%s)", v, s); return nc; @@ -71,7 +71,7 @@ int model_step(ModelDesc* model, double* model_time, double stop_time) /* Scalar signals. */ ModelSignalIndex counter = - m->model.index((ModelDesc*)m, "scalar_vector", "counter"); + signal_index((ModelDesc*)m, "scalar_vector", "counter"); if (counter.scalar == NULL) return -EINVAL; *(counter.scalar) += 1; diff --git a/dse/modelc/examples/simer/model.c b/dse/modelc/examples/simer/model.c index e68e4c3..19bbe59 100644 --- a/dse/modelc/examples/simer/model.c +++ b/dse/modelc/examples/simer/model.c @@ -33,7 +33,7 @@ ModelDesc* model_create(ModelDesc* model) if (getenv("COUNTER_NAME")) { counter_name = getenv("COUNTER_NAME"); } - m->counter = m->model.index((ModelDesc*)m, "data", counter_name); + m->counter = signal_index((ModelDesc*)m, "data", counter_name); if (m->counter.scalar == NULL) log_fatal("Signal not found (%s)", counter_name); /* Set initial values. */ diff --git a/dse/modelc/model.h b/dse/modelc/model.h index c560dd5..2e3dc13 100644 --- a/dse/modelc/model.h +++ b/dse/modelc/model.h @@ -5,6 +5,7 @@ #ifndef DSE_MODELC_MODEL_H_ #define DSE_MODELC_MODEL_H_ +#include #include #include @@ -188,7 +189,6 @@ DLL_PUBLIC const char* model_instance_annotation( /* Signal Interface. */ - typedef int (*BinarySignalAppendFunc)( SignalVector* sv, uint32_t index, void* data, uint32_t len); typedef int (*BinarySignalResetFunc)(SignalVector* sv, uint32_t index); @@ -249,8 +249,12 @@ typedef struct SignalVector { /* Provided by ModelC (virtual methods of SignalVectorVTable). */ +DLL_PUBLIC ModelSignalIndex signal_index( + ModelDesc* m, const char* vname, const char* name); +DLL_PUBLIC int signal_read( + SignalVector* sv, uint32_t index, uint8_t** data, size_t* len); DLL_PUBLIC int signal_append( - SignalVector* sv, uint32_t index, void* data, uint32_t len); + SignalVector* sv, uint32_t index, uint8_t* data, size_t len); DLL_PUBLIC int signal_reset(SignalVector* sv, uint32_t index); DLL_PUBLIC int signal_release(SignalVector* sv, uint32_t index); DLL_PUBLIC void* signal_codec(SignalVector* sv, uint32_t index); diff --git a/dse/modelc/model/model.c b/dse/modelc/model/model.c index b3691c4..07fbecc 100644 --- a/dse/modelc/model/model.c +++ b/dse/modelc/model/model.c @@ -584,11 +584,11 @@ NULL : The specified annotation was not found. */ -const char* model_annotation(ModelDesc* m, const char* name) +const char* model_annotation(ModelDesc* model, const char* name) { - if (m && m->mi) { + if (model && model->mi) { YamlNode* a = dse_yaml_find_node( - m->mi->model_definition.doc, "metadata/annotations"); + model->mi->model_definition.doc, "metadata/annotations"); if (a) return dse_yaml_get_scalar(a, name); } return NULL; @@ -618,10 +618,10 @@ NULL : The specified annotation was not found. */ -const char* model_instance_annotation(ModelDesc* m, const char* name) +const char* model_instance_annotation(ModelDesc* model, const char* name) { - if (m && m->mi) { - YamlNode* a = dse_yaml_find_node(m->mi->spec, "annotations"); + if (model && model->mi) { + YamlNode* a = dse_yaml_find_node(model->mi->spec, "annotations"); if (a) return dse_yaml_get_scalar(a, name); } return NULL; diff --git a/dse/modelc/model/signal.c b/dse/modelc/model/signal.c index e609c0f..bf15730 100644 --- a/dse/modelc/model/signal.c +++ b/dse/modelc/model/signal.c @@ -437,6 +437,93 @@ void model_sv_destroy(SignalVector* sv) } +/** +signal_index +============ + +A model may use this method to index a signal that is contained within the +Signal Vectors of the Model Descriptor. + +Parameters +---------- +model (ModelDesc*) +: The Model Descriptor object representing an instance of this model. + +vname (const char*) +: The name (alias) of the Signal Vector. + +name (const char*) +: The name of the signal within the Signal Vector. When set to NULL the index + will match on Signal Vector (vanme) only. + +Returns +------- +ModelSignalIndex +: An index. When valid, either the `scalar` or `binary` fields will be set to + a valid pointer (i.e. not NULL). When `sname` is not specified the index will + contain a valid pointer to a Signal Vector object only (i.e. both `scalar` + and `binary` will be set to NULL). + +*/ +ModelSignalIndex signal_index( + ModelDesc* model, const char* vname, const char* name) +{ + if (model && model->index) { + return model->index(model, vname, name); + } + return (ModelSignalIndex){}; +} + + +/** +signal_read +=========== + +Read data from the specified binary signal. Returns pointer to the internal +binary signal buffers. + +Parameters +---------- +sv (SignalVector*) +: The Signal Vector object containing the signal. + +index (uint32_t) +: Index of the signal in the Signal Vector object. + +data (uint8_t*) +: Address/pointer to the data of the binary signal. + +len (size_t) +: Length of the data. + +Returns +------- +0 +: The operation completed without error. + +-EINVAL (-22) +: Bad arguments. + +<>0 +: Indicates an error condition. Inspect `errno` for additional information. +*/ +inline int signal_read( + SignalVector* sv, uint32_t index, uint8_t** data, size_t* len) +{ + if (data == NULL || len == NULL) return -EINVAL; + *data = NULL; + *len = 0; + + if (sv && index < sv->count && sv->is_binary) { + *data = (uint8_t*)sv->binary[index]; + *len = (size_t)sv->length[index]; + return 0; + } else { + return -EINVAL; + } +} + + /** signal_append ============= @@ -452,10 +539,10 @@ sv (SignalVector*) index (uint32_t) : Index of the signal in the Signal Vector object. -data (void*) +data (uint8_t*) : Address/pointer to the data which should be appended to the binary signal. -len (uint32_t) +len (size_t) : Length of the provided data buffer being appended. Returns @@ -473,11 +560,11 @@ Returns : Indicates an error condition. Inspect `errno` for additional information. */ inline int signal_append( - SignalVector* sv, uint32_t index, void* data, uint32_t len) + SignalVector* sv, uint32_t index, uint8_t* data, size_t len) { if (sv && index < sv->count && sv->is_binary) { if (sv->vtable.append) { - return sv->vtable.append(sv, index, data, len); + return sv->vtable.append(sv, index, (void*)data, len); } else { return -ENOSYS; } diff --git a/extra/external/oss_repos.cmake b/extra/external/oss_repos.cmake index 6b788ba..78dcd9d 100644 --- a/extra/external/oss_repos.cmake +++ b/extra/external/oss_repos.cmake @@ -7,7 +7,6 @@ # OSS Projects can be listed here, even if they are not used by the # External Projects, to maintain an accurate inventory of OSS Projects. -set(ExternalProject__DSE_NCODEC__URL https://github.com/boschglobal/dse.standards/archive/refs/tags/v1.0.8.tar.gz) set(ExternalProject__EVENT__URL https://github.com/libevent/libevent/archive/refs/tags/release-2.1.12-stable.tar.gz) set(ExternalProject__YAML__URL https://github.com/yaml/libyaml/archive/0.2.5.tar.gz) set(ExternalProject__MSGPACK__URL https://github.com/msgpack/msgpack-c/archive/refs/tags/cpp-3.3.0.tar.gz) diff --git a/tests/cmocka/model/interface/test_model_api.c b/tests/cmocka/model/interface/test_model_api.c index 9d342da..fde7280 100644 --- a/tests/cmocka/model/interface/test_model_api.c +++ b/tests/cmocka/model/interface/test_model_api.c @@ -215,10 +215,10 @@ void test_model_api__binary_stream_reset(void** state) mock, BINARY_INST_NAME, b_checks, ARRAY_SIZE(b_checks), NULL); /* Inject some binary data, if reset is called, this will be ignored. */ SignalVector* sv = mock->sv_network_tx; - char foobar[100] = "foobar"; + unsigned char foobar[100] = "foobar"; for (int j = 0; j < 2; j++) { signal_reset(sv, j); - signal_append(sv, j, foobar, strlen(foobar) + 1); + signal_append(sv, j, foobar, strlen((char*)foobar) + 1); } /* Step the model. */ assert_int_equal(simmock_step(mock, true), 0); diff --git a/tests/cmocka/model/test_signal.c b/tests/cmocka/model/test_signal.c index 342267d..32adfe4 100644 --- a/tests/cmocka/model/test_signal.c +++ b/tests/cmocka/model/test_signal.c @@ -89,6 +89,65 @@ static int test_teardown(void** state) } +typedef struct IndexTC { + const char* v; + const char* s; + bool is_binary; + uint32_t vi; + uint32_t si; +} IndexTC; + +void test_signal__index(void** state) +{ + ModelCMock* mock = *state; + ModelDesc* m = mock->mi->model_desc; + SignalVector* sv_save = mock->mi->model_desc->sv; + + assert_non_null(m); + assert_non_null(m->index); + + /* find the indexes. */ + SignalVector* sv = sv_save; + uint32_t scalar_index = 0; + while (sv && sv->name) { + if (strcmp(sv->name, "scalar") == 0) break; + /* Next signal vector. */ + sv++; + scalar_index++; + } + sv = sv_save; + uint32_t binary_index = 0; + while (sv && sv->name) { + if (strcmp(sv->name, "binary") == 0) break; + /* Next signal vector. */ + sv++; + binary_index++; + } + + IndexTC tc[] = { + { .v = "scalar_vector", .s = "scalar_foo", .vi = scalar_index, .si = 0, .is_binary = false }, + { .v = "scalar_vector", .s = "scalar_bar", .vi = scalar_index, .si = 1, .is_binary = false }, + { .v = "binary_vector", .s = "binary_foo", .vi = binary_index, .si = 0, .is_binary = true }, + { .v = "binary_vector", .s = "binary_bar", .vi = binary_index, .si = 1, .is_binary = true }, + }; + // Check the test cases. + for (size_t i = 0; i < ARRAY_SIZE(tc); i++) { + ModelSignalIndex msi = signal_index(m, tc[i].v, tc[i].s); + assert_non_null(msi.sv); + assert_string_equal(msi.sv->alias, tc[i].v); + assert_int_equal(msi.vector, tc[i].vi); + assert_int_equal(msi.signal, tc[i].si); + if (tc[i].is_binary) { + assert_null(msi.scalar); + assert_non_null(msi.binary); + } else { + assert_non_null(msi.scalar); + assert_null(msi.binary); + } + } +} + + void test_signal__scalar(void** state) { ModelCMock* mock = *state; @@ -178,11 +237,16 @@ void test_signal__binary(void** state) "application/custom-stream", }; for (uint32_t i = 0; i < sv->count; i++) { - char* test_val = strdup(sv->signal[i]); - uint32_t test_val_len = strlen(test_val) + 1; + unsigned char* test_val = (unsigned char*)strdup(sv->signal[i]); + uint32_t test_val_len = strlen((char*)test_val) + 1; assert_string_equal(sv->signal[i], expected_names[i]); assert_string_equal(sv->mime_type[i], expected_mime_types[i]); + uint8_t* buffer; + size_t buffer_len; /* Check the value. */ + signal_read(sv, i, &buffer, &buffer_len); + assert_null(buffer); + assert_int_equal(buffer_len, 0); assert_null(sv->binary[i]); assert_int_equal(sv->length[i], 0); assert_int_equal(sv->buffer_size[i], 0); @@ -191,9 +255,12 @@ void test_signal__binary(void** state) /* Append to the value. */ signal_append(sv, i, test_val, test_val_len); assert_non_null(sv->binary[i]); - assert_string_equal((char*)sv->binary[i], test_val); + assert_string_equal((char*)sv->binary[i], (char*)test_val); assert_int_equal(sv->length[i], test_val_len); assert_int_equal(sv->buffer_size[i], test_val_len); + signal_read(sv, i, &buffer, &buffer_len); + assert_string_equal((char*)buffer, (char*)test_val); + assert_int_equal(buffer_len, test_val_len); /* Reset the value. */ signal_reset(sv, i); assert_true(sv->reset_called[i]); @@ -206,6 +273,8 @@ void test_signal__binary(void** state) assert_non_null(sv->binary[i]); assert_int_equal(sv->length[i], test_val_len); assert_int_equal(sv->buffer_size[i], test_val_len); + signal_read(sv, i, &buffer, &buffer_len); + assert_int_equal(buffer_len, test_val_len); /* Release the value. */ signal_release(sv, i); assert_null(sv->binary[i]); @@ -304,8 +373,8 @@ void test_signal__binary_echo(void** state) assert_int_equal(sv->length[1], 0); assert_false(sv->reset_called[0]); assert_false(sv->reset_called[1]); - char* test_val = strdup(sv->signal[0]); - uint32_t test_val_len = strlen(test_val) + 1; + unsigned char* test_val = (unsigned char*)strdup(sv->signal[0]); + uint32_t test_val_len = strlen((char*)test_val) + 1; /* Append to one signal. */ @@ -343,6 +412,7 @@ int run_signal_tests(void) void* t = test_teardown; const struct CMUnitTest tests[] = { + cmocka_unit_test_setup_teardown(test_signal__index, s, t), cmocka_unit_test_setup_teardown(test_signal__scalar, s, t), cmocka_unit_test_setup_teardown(test_signal__binary, s, t), cmocka_unit_test_setup_teardown(test_signal__annotations, s, t),