• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nasa / trick / 20283694683

16 Dec 2025 09:44PM UTC coverage: 55.586% (-0.3%) from 55.934%
20283694683

push

github

web-flow
Add vs support for stl vector, deque, and array containers of supported data types (#1996)

* Added TV GUI side support for vectors

* Initial check-in for variable server to support vector.

* Added accessor functions to ATTRIBUTES to get stl container size and element at index so mm ref_dim can get element at index for a vector as getting element of an array plus bounds check for vector.

* Added support to deque and array as they be treated similar to vector.

* Updated the test due to vs vector support change.

* Added vector/deque/array of TRICK_STRUCTURED data type support.

* Updated to support vector<bool>.

* Updated to support vector/deque/array of *.

* Updated to support vector/deque/array of TRICK_ENUMERATED and display enum name for the stl enum elements for TV; also updated to show bool element as normal bool var for TV.

* Made elements of vector/array/deque to be editable from TV.

* Not to change the stl type to element when not indexing.

* Added special handling for updating vector of bool since std::vector<bool> is optimized to store bits compactly (8 bools per byte) in c++.

* Need to print NULL for the newly added ATTRIBUTES assessor function for filed attributes in io src file.

* Added var_get_stl_size command to vs sesssion and updated tv to show index range as constraint arrays for vector/deque/array when adding a var.

* Added test cases for vector/deque/array and also changed to use its own vs msg type for var_get_stl_size.

* Removed the unused function as it was changed to use clang api instead.

* Updated not to use static temp attr for working on storing vector<boo> to its ref_attr.

---------

Co-authored-by: plherrin <pherring04@gmail.com>

46 of 212 new or added lines in 8 files covered. (21.7%)

2 existing lines in 2 files now uncovered.

12508 of 22502 relevant lines covered (55.59%)

304713.82 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

18.52
/trick_source/sim_services/VariableServer/VariableServerSession_commands.cpp
1

2
#include <string.h>
3
#include <iostream>
4
#include <sstream>
5
#include <stdlib.h>
6
#include <udunits2.h>
7
#include "trick/VariableServerSession.hh"
8
#include "trick/variable_server_message_types.h"
9
#include "trick/memorymanager_c_intf.h"
10
#include "trick/exec_proto.h"
11
#include "trick/command_line_protos.h"
12
#include "trick/message_proto.h"
13
#include "trick/message_type.h"
14
#include "trick/TrickConstant.hh"
15
#include "trick/sie_c_intf.h"
16
#include "trick/UdUnits.hh"
17
#include "trick/map_trick_units_to_udunits.hh"
18

19

20
int Trick::VariableServerSession::var_add(std::string in_name) {
3✔
21
    VariableReference * new_var;
22
    if (in_name == "time") {
3✔
23
        new_var = new VariableReference(in_name, &_time);
×
24
    } else {
25
        new_var = new VariableReference(in_name);
3✔
26
    }
27

28
    _session_variables.push_back(new_var) ;
3✔
29

30
    return(0) ;
3✔
31
}
32

33
int Trick::VariableServerSession::var_add(std::string var_name, std::string units_name) {
×
34
    var_add(var_name) ;
×
35
    var_units(var_name, units_name) ;
×
36
    return(0) ;
×
37
}
38

39
// Helper function for var_send_once
40
std::vector<std::string> split (const std::string& str, const char delim) {
×
41
    std::stringstream ss(str);
×
42
    std::string s;
×
43
    std::vector<std::string> ret;
×
44
    while (std::getline(ss, s, delim)) {
×
45
        ret.push_back(s);
×
46
    }
47
    return ret;
×
48
}
49

50
int Trick::VariableServerSession::var_send_once(std::string in_name, int num_vars) {
×
51
    std::vector<std::string> var_names = split(in_name, ',');
×
52

53
    if (var_names.size() != num_vars) {
×
54
        message_publish(MSG_ERROR, "Number of variables sent to var_send_once (%d) does not match num_vars (%d).\n", var_names.size(), num_vars);
×
55
        return -1;
×
56
    }
57

58
    std::vector<VariableReference *> given_vars;
×
59
    for (auto& varName : var_names) {
×
60
        VariableReference * new_var;
61
        if (varName == "time") {
×
62
            new_var = new VariableReference(varName, &_time);
×
63
        } else {
64
            new_var = new VariableReference(varName);
×
65
        }
66
        given_vars.push_back(new_var);
×
67
    }
68
    copy_sim_data(given_vars, false);
×
69
    write_data(given_vars, VS_SEND_ONCE);
×
70

71
    return(0) ;
×
72
}
73

74

75
int Trick::VariableServerSession::var_remove(std::string in_name) {
×
76

77
    for (unsigned int ii = 0 ; ii < _session_variables.size() ; ii++ ) {
×
78
        std::string var_name = _session_variables[ii]->getName();
×
79
        if ( ! var_name.compare(in_name) ) {
×
80
            delete _session_variables[ii];
×
81
            _session_variables.erase(_session_variables.begin() + ii) ;
×
82
            break ;
×
83
        }
84
    }
85

86
    return(0) ;
×
87

88
}
89

90
int Trick::VariableServerSession::var_units(std::string var_name, std::string units_name) {    
×
91
    VariableReference * variable = find_session_variable(var_name);
×
92

93
    if (variable == NULL) {
×
94
        // TODO: ERROR LOGGER HERE
95
        return -1;
×
96
    }
97

98
    return variable->setRequestedUnits(units_name);
×
99
}
100

NEW
101
int Trick::VariableServerSession::var_get_stl_size(std::string in_name)
×
102
{
103
    char buf[12];
NEW
104
    int size = 0;
×
NEW
105
    bool error = false;
×
106

NEW
107
    REF2 *ref = ref_attributes(in_name.c_str());
×
108

NEW
109
    if (ref == NULL)
×
110
    {
NEW
111
        error = true;
×
112
    }
113
    else
114
    {
115
        // Check if this is an STL container with a get_stl_size function
NEW
116
        ATTRIBUTES *attr = ref->attr;
×
NEW
117
        if (attr == NULL)
×
118
        {
NEW
119
            error = true;
×
120
        }
NEW
121
        else if (attr->get_stl_size == NULL)
×
122
        {
NEW
123
            error = true;
×
124
        }
125
        else
126
        {
127
            // Call the get_stl_size accessor function
NEW
128
            size = attr->get_stl_size(ref->address);
×
129
        }
NEW
130
        free(ref);
×
131
    }
132

NEW
133
    unsigned int msg_type = VS_GET_STL_SIZE;
×
134

NEW
135
    if (_binary_data)
×
136
    {
137
        // Send binary: message_type (4 bytes) + size (4 bytes)
NEW
138
        memcpy(buf, &msg_type, sizeof(msg_type));
×
NEW
139
        memcpy(buf + 4, &size, sizeof(size));
×
140

NEW
141
        if (_debug >= 2)
×
142
        {
NEW
143
            message_publish(MSG_DEBUG, "%p tag=<%s> var_server sending STL size %d (binary)\n", _connection,
×
NEW
144
                            _connection->getClientTag().c_str(), size);
×
145
        }
146

NEW
147
        _connection->write(buf, 8);
×
148
    }
149
    else
150
    {
151
        // Send ASCII: "message_type\tsize"
NEW
152
        std::string message = std::to_string(msg_type) + "\t";
×
NEW
153
        if (error)
×
154
        {
NEW
155
            message += "BAD_REF";
×
156
        }
157
        else
158
        {
NEW
159
            message += std::to_string(size);
×
160
        }
NEW
161
        message += "\n";
×
162

NEW
163
        if (_debug >= 2)
×
164
        {
NEW
165
            message_publish(MSG_DEBUG, "%p tag=<%s> var_server sending STL size %d (ASCII)\n", _connection,
×
NEW
166
                            _connection->getClientTag().c_str(), size);
×
167
        }
168

NEW
169
        _connection->write(message);
×
170
    }
171

NEW
172
    return 0;
×
173
}
174

UNCOV
175
int Trick::VariableServerSession::var_exists(std::string in_name) {
×
176
    char buf1[5] ;
177
    bool error = false ;
×
178

179
    unsigned int msg_type ;
180
    REF2* var_ref = ref_attributes(in_name.c_str());
×
181

182
    if ( var_ref == (REF2*)NULL ) {
×
183
        error = true;
×
184
    }
185

186
    if (_binary_data) {
×
187
        /* send binary 1 or 0 */
188
        msg_type = VS_VAR_EXISTS ;
×
189
        memcpy(buf1, &msg_type , sizeof(msg_type)) ;
×
190

191
        buf1[4] = (error==false);
×
192

193
        if (_debug >= 2) {
×
194
            message_publish(MSG_DEBUG, "%p tag=<%s> var_server sending 1 binary byte\n", _connection, _connection->getClientTag().c_str());
×
195
        }
196

197
        _connection->write(buf1, 5);
×
198
    } else {
199
        /* send ascii "1" or "0" */
200
        sprintf(buf1, "%d\t%d\n", VS_VAR_EXISTS, (error==false));
×
201
        if (_debug >= 2) {
×
202
            message_publish(MSG_DEBUG, "%p tag=<%s> var_server sending:\n%s\n", _connection, _connection->getClientTag().c_str(), buf1) ;
×
203
        }
204
        std::string write_string(buf1);
×
205
        if (write_string.length() != strlen(buf1)) {
×
206
            std::cout << "PROBLEM WITH STRING LENGTH: VAR_EXISTS ASCII" << std::endl;
×
207
        }
208
        _connection->write(write_string);
×
209
    }
210

211
    return(0) ;
×
212
}
213

214
int Trick::VariableServerSession::var_clear() {
×
215

216
    while( !_session_variables.empty() ) {
×
217
        delete _session_variables.back();
×
218
        _session_variables.pop_back();
×
219
    }
220

221
    return(0) ;
×
222
}
223

224
int Trick::VariableServerSession::var_send() {
×
225
    copy_sim_data();
×
226
    write_data();
×
227
    return(0) ;
×
228
}
229

230
int Trick::VariableServerSession::var_cycle(double in_rate) {
×
231
    _update_rate = in_rate ;
×
232
    _cycle_tics = (long long)(_update_rate * exec_get_time_tic_value()) ;
×
233
    return(0) ;
×
234
}
235

236
int Trick::VariableServerSession::var_exit() {
×
237
    _exit_cmd = true ;
×
238
    return(0) ;
×
239
}
240

241
int Trick::VariableServerSession::var_validate_address(bool on_off) {
×
242
    _validate_address = on_off ;
×
243
    return(0) ;
×
244
}
245

246
int Trick::VariableServerSession::var_debug(int level) {
1✔
247
    _debug = level ;
1✔
248
    return(0) ;
1✔
249
}
250

251
int Trick::VariableServerSession::var_ascii() {
1✔
252
    _binary_data = 0 ;
1✔
253
    return(0) ;
1✔
254
}
255

256
int Trick::VariableServerSession::var_binary() {
2✔
257
    _binary_data = 1 ;
2✔
258
    return(0) ;
2✔
259
}
260

261
int Trick::VariableServerSession::var_binary_nonames() {
×
262
    _binary_data = 1 ;
×
263
    _binary_data_nonames = 1 ;
×
264
    return(0) ;
×
265
}
266

267
int Trick::VariableServerSession::var_set_copy_mode(int mode) {
3✔
268
    if ( mode >= VS_COPY_ASYNC and mode <= VS_COPY_TOP_OF_FRAME ) {
3✔
269
        _copy_mode = (VS_COPY_MODE)mode ;
3✔
270
        if ( _copy_mode == VS_COPY_SCHEDULED ) {
3✔
271
            long long sim_time_tics ;
272
            sim_time_tics = exec_get_time_tics() ;
2✔
273
            // round the next call time to a multiple of the cycle
274
            sim_time_tics -= sim_time_tics % _cycle_tics ;
2✔
275
            _next_tics = sim_time_tics + _cycle_tics ;
2✔
276

277
            sim_time_tics = exec_get_freeze_time_tics() ;
2✔
278
            // round the next call time to a multiple of the cycle
279
            sim_time_tics -= sim_time_tics % _cycle_tics ;
2✔
280
            _freeze_next_tics = sim_time_tics + _cycle_tics ;
2✔
281

282
        } else {
283
            _next_tics = TRICK_MAX_LONG_LONG ;
1✔
284
        }
285
        return 0 ;
3✔
286
    }
287
    return -1 ;
×
288
}
289

290
int Trick::VariableServerSession::var_set_write_mode(int mode) {
3✔
291
    if ( mode >= VS_WRITE_ASYNC and mode <= VS_WRITE_WHEN_COPIED ) {
3✔
292
        _write_mode = (VS_WRITE_MODE)mode ;
3✔
293
        return 0 ;
3✔
294
    }
295
    return -1 ;
×
296
}
297

298
int Trick::VariableServerSession::var_sync(int mode) {
3✔
299

300
    switch (mode) {
3✔
301
        case 1:
1✔
302
            var_set_copy_mode(VS_COPY_SCHEDULED) ;
1✔
303
            var_set_write_mode(VS_WRITE_ASYNC) ;
1✔
304
            break ;
1✔
305
        case 2:
1✔
306
            var_set_copy_mode(VS_COPY_SCHEDULED) ;
1✔
307
            var_set_write_mode(VS_WRITE_WHEN_COPIED) ;
1✔
308
            break ;
1✔
309
        case 0:
1✔
310
        default:
311
            var_set_copy_mode(VS_COPY_ASYNC) ;
1✔
312
            var_set_write_mode(VS_WRITE_ASYNC) ;
1✔
313
            break ;
1✔
314
    }
315

316
    return 0 ;
3✔
317
}
318

319
int Trick::VariableServerSession::var_set_frame_multiple(unsigned int mult) {
×
320
    _frame_multiple = mult ;
×
321
    return 0 ;
×
322
}
323

324
int Trick::VariableServerSession::var_set_frame_offset(unsigned int offset) {
×
325
    _frame_offset = offset ;
×
326
    return 0 ;
×
327
}
328

329
int Trick::VariableServerSession::var_set_freeze_frame_multiple(unsigned int mult) {
×
330
    _freeze_frame_multiple = mult ;
×
331
    return 0 ;
×
332
}
333

334
int Trick::VariableServerSession::var_set_freeze_frame_offset(unsigned int offset) {
×
335
    _freeze_frame_offset = offset ;
×
336
    return 0 ;
×
337
}
338

339
int Trick::VariableServerSession::var_byteswap(bool on_off) {
×
340
    _byteswap = on_off ;
×
341
    return(0) ;
×
342
}
343

344
bool Trick::VariableServerSession::get_send_stdio() {
×
345
    return _send_stdio ;
×
346
}
347

348
int Trick::VariableServerSession::set_send_stdio(bool on_off) {
×
349
    _send_stdio = on_off ;
×
350
    return(0) ;
×
351
}
352

353
int Trick::VariableServerSession::send_list_size() {
×
354
    
355
    unsigned int msg_type = VS_LIST_SIZE;
×
356
    int var_count = _session_variables.size();
×
357

358
    // send number of variables
359
    if (_binary_data) {
×
360
        // send in the binary message header format:
361
        // <message_indicator><message_size><number_of_variables>
362
        char buf1[12] ;
363

364
        unsigned int msg_type = VS_LIST_SIZE;
×
365
        memcpy(buf1, &msg_type , sizeof(msg_type)) ;
×
366

367
        memset(&(buf1[4]), 0, sizeof(int)); // message size = 0
×
368
        memcpy(&(buf1[8]), &var_count, sizeof(var_count));
×
369

370
        if (_debug >= 2) {
×
371
            message_publish(MSG_DEBUG, "%p tag=<%s> var_server sending %d event variables\n", _connection, _connection->getClientTag().c_str(), var_count);
×
372
        }
373

374
        _connection->write(buf1, sizeof (buf1));
×
375
    } else {
376
        std::stringstream write_string;
×
377
        write_string << VS_LIST_SIZE << "\t" << var_count << "\n";
×
378
        // ascii
379
        if (_debug >= 2) {
×
380
            message_publish(MSG_DEBUG, "%p tag=<%s> var_server sending number of event variables:\n%s\n", _connection, _connection->getClientTag().c_str(), write_string.str().c_str()) ;
×
381
        }
382

383
        _connection->write(write_string.str());
×
384
    }
385

386
    return 0 ;
×
387
}
388

389
int Trick::VariableServerSession::transmit_file(std::string filename) {
×
390
    const unsigned int packet_size = 4095 ;
×
391
    FILE * fp ;
392
    unsigned int file_size ;
393
    unsigned int current_size = 0 ;
×
394
    unsigned int bytes_read ;
395
    char buffer[packet_size+1] ;
396
    int ret ;
397

398
    if (_debug >= 2) {
×
399
        message_publish(MSG_DEBUG,"%p tag=<%s> var_server opening %s.\n", _connection, _connection->getClientTag().c_str(), filename.c_str()) ;
×
400
    }
401

402
    if ((fp = fopen(filename.c_str() , "r")) == NULL ) {
×
403
        message_publish(MSG_ERROR,"Variable Server Error: Cannot open %s.\n", filename.c_str()) ;
×
404
        sprintf(buffer, "%d\t-1\n", VS_SIE_RESOURCE) ;
×
405
        std::string message(buffer);
×
406
        _connection->write(message);
×
407
        return(-1) ;
×
408
    }
409

410
    fseek(fp , 0L, SEEK_END) ;
×
411
    file_size = ftell(fp) ;
×
412

413
    sprintf(buffer, "%d\t%u\n\0" , VS_SIE_RESOURCE, file_size) ;
×
414
    std::string message(buffer);
×
415
    _connection->write(message);
×
416
    rewind(fp) ;
×
417

418
    // Switch to blocking writes since this could be a large transfer.
419
    if (_connection->setBlockMode(true)) {
×
420
        message_publish(MSG_DEBUG,"Variable Server Error: Failed to set socket to blocking mode.\n");
×
421
    }
422

423
    while ( current_size < file_size ) {
×
424
        bytes_read = fread(buffer , 1 , packet_size , fp) ;
×
425
        message = std::string(buffer);
×
426
        message.resize(bytes_read);
×
427
        ret = _connection->write(message);
×
428
        if (ret != (int)bytes_read) {
×
429
            message_publish(MSG_ERROR,"Variable Server Error: Failed to send file. Bytes read: %d Bytes sent: %d\n", bytes_read, ret) ;
×
430
            return(-1);
×
431
        }
432
        current_size += bytes_read ;
×
433
    }
434

435
    // Switch back to non-blocking writes.
436
    if (_connection->setBlockMode(false)) {
×
437
        message_publish(MSG_DEBUG,"Variable Server Error: Failed to set socket to non-blocking mode.\n");
×
438
        return(-1);
×
439
    }
440

441
    return(0) ;
×
442
}
443

444
int Trick::VariableServerSession::send_file(std::string file_name) {
×
445
    return transmit_file(file_name) ;
×
446
}
447

448
int Trick::VariableServerSession::send_sie_resource() {
×
449
    sie_append_runtime_objs() ;
×
450
    //return transmit_file(std::string(command_line_args_get_default_dir()) + "/S_sie.resource") ;
451
    // Use the runtime sie dir instead of the default dir as sie_append_runtime_objs() 
452
    // may have moved the sie resource file and also always uses the runtime sie dir.
453
    return transmit_file(std::string(sie_get_runtime_sie_dir()) + "/S_sie.resource") ;
×
454
}
455

456
int Trick::VariableServerSession::send_sie_class() {
×
457
    sie_class_attr_map_print_xml() ;
×
458
    //return transmit_file(std::string(command_line_args_get_default_dir()) + "/" + "S_sie_class.xml") ;
459
    // Use the runtime sie dir instead of the default dir as sie_class_attr_map_print_xml()
460
    // always uses the runtime sie dir.
461
    return transmit_file(std::string(sie_get_runtime_sie_dir()) + "/" + "S_sie_class.xml") ;
×
462
}
463

464
int Trick::VariableServerSession::send_sie_enum() {
×
465
    sie_enum_attr_map_print_xml() ;
×
466
    //return transmit_file(std::string(command_line_args_get_default_dir()) + "/" + "S_sie_enum.xml") ;
467
    // Use the runtime sie dir instead of the default dir as sie_enum_attr_map_print_xml()
468
    // always uses the runtime sie dir.
469
    return transmit_file(std::string(sie_get_runtime_sie_dir()) + "/" + "S_sie_enum.xml") ;
×
470
}
471

472
int Trick::VariableServerSession::send_sie_top_level_objects() {
×
473
    sie_top_level_objects_print_xml() ;
×
474
    //return transmit_file(std::string(command_line_args_get_default_dir()) + "/" + "S_sie_top_level_objects.xml") ;
475
    // Use the runtime sie dir instead of the default dir as sie_top_level_objects_print_xml()
476
    // always uses the runtime sie dir.
477
    return transmit_file(std::string(sie_get_runtime_sie_dir()) + "/" + "S_sie_top_level_objects.xml") ;
×
478
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc