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

nasa / trick / 16179091313

09 Jul 2025 08:05PM UTC coverage: 55.919% (-0.03%) from 55.948%
16179091313

Pull #1922

github

web-flow
Merge 04a907d09 into d9a49c036
Pull Request #1922: Added a check for unconstrained dimensions boundary.

14 of 25 new or added lines in 3 files covered. (56.0%)

4 existing lines in 2 files now uncovered.

12334 of 22057 relevant lines covered (55.92%)

252313.66 hits per line

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

74.06
/trick_source/sim_services/VariableServer/VariableReference.cpp
1
#include <stdlib.h>
2
#include <iostream>
3
#include <udunits2.h>
4
#include <math.h> // for fpclassify
5
#include <iomanip> // for setprecision
6
#include <string.h>
7
#include <sstream>
8

9
#include "trick/VariableReference.hh"
10
#include "trick/memorymanager_c_intf.h"
11
#include "trick/wcs_ext.h"
12
#include "trick/map_trick_units_to_udunits.hh"
13
#include "trick/message_proto.h"
14
#include "trick/message_type.h"
15
#include "trick/UdUnits.hh"
16
#include "trick/bitfield_proto.h"
17
#include "trick/trick_byteswap.h"
18

19

20
// Static variables to be addresses that are known to be the error ref address
21
int Trick::VariableReference::_bad_ref_int = 0 ;
22
int Trick::VariableReference::_do_not_resolve_bad_ref_int = 0 ;
23

24
REF2* Trick::VariableReference::make_error_ref(std::string in_name) {
3✔
25
    REF2* new_ref;
26
    new_ref = (REF2*)calloc(1, sizeof(REF2));
3✔
27
    new_ref->reference = strdup(in_name.c_str()) ;
3✔
28
    new_ref->units = NULL ;
3✔
29
    new_ref->address = (char *)&_bad_ref_int ;
3✔
30
    new_ref->attr = (ATTRIBUTES*)calloc(1, sizeof(ATTRIBUTES)) ;
3✔
31
    new_ref->attr->type = TRICK_NUMBER_OF_TYPES ;
3✔
32
    new_ref->attr->units = (char *)"--" ;
3✔
33
    new_ref->attr->size = sizeof(int) ;
3✔
34
    return new_ref;
3✔
35
}
36

37
REF2* Trick::VariableReference::make_do_not_resolve_ref(std::string in_name) {
2✔
38
    REF2* new_ref;
39
    new_ref = (REF2*)calloc(1, sizeof(REF2));
2✔
40
    new_ref->reference = strdup(in_name.c_str()) ;
2✔
41
    new_ref->units = NULL ;
2✔
42
    new_ref->address = (char *)&_do_not_resolve_bad_ref_int ;
2✔
43
    new_ref->attr = (ATTRIBUTES*)calloc(1, sizeof(ATTRIBUTES)) ;
2✔
44
    new_ref->attr->type = TRICK_NUMBER_OF_TYPES ;
2✔
45
    new_ref->attr->units = (char *)"--" ;
2✔
46
    new_ref->attr->size = sizeof(int) ;
2✔
47
    return new_ref;
2✔
48
}
49

50
// Helper function to deal with time variable
51
REF2* make_time_ref(double * time) {
×
52
    REF2* new_ref;
53
    new_ref = (REF2*)calloc(1, sizeof(REF2));
×
54
    new_ref->reference = strdup("time") ;
×
55
    new_ref->units = strdup("s") ;
×
56
    new_ref->address = (char *)time ;
×
57
    new_ref->attr = (ATTRIBUTES*)calloc(1, sizeof(ATTRIBUTES)) ;
×
58
    new_ref->attr->type = TRICK_DOUBLE ;
×
59
    new_ref->attr->units = strdup("s") ;
×
60
    new_ref->attr->size = sizeof(double) ;
×
61
    return new_ref;
×
62
}
63

64
Trick::VariableReference::VariableReference(std::string var_name, double* time) : _staged(false), _write_ready(false) {
×
65
    if (var_name != "time") {
×
66
        ASSERT(0);
67
    }
68

69
    _var_info = make_time_ref(time);
×
70

71
    // Set up member variables
72
    _address = _var_info->address;
×
73
    _size = _var_info->attr->size ;
×
74
    _deref = false;
×
75

76
    // Deal with weirdness around string vs wstring
77
    _trick_type = _var_info->attr->type ;
×
78

79
    // Allocate stage and write buffers
80
    _stage_buffer = calloc(_size, 1) ;
×
81
    _write_buffer = calloc(_size, 1) ;
×
82

83
    _conversion_factor = cv_get_trivial();
×
84
    _base_units = _var_info->attr->units;
×
85
    _requested_units = "s";
×
86
    _name = _var_info->reference;
×
87
}
×
88

89
Trick::VariableReference::VariableReference(std::string var_name) : _staged(false), _write_ready(false) {
8,055✔
90

91
    if (var_name == "time") {
8,055✔
92
        ASSERT(0);
93
    } else {
94
        // get variable attributes from memory manager
95
        _var_info = ref_attributes(var_name.c_str());
8,055✔
96
    }
97

98
    // Handle error cases
99
    if ( _var_info == NULL ) {
8,055✔
100
        // TODO: ERROR LOGGER sendErrorMessage("Variable Server could not find variable %s.\n", var_name);
101
        // PRINTF IS NOT AN ERROR LOGGER @me
102
        message_publish(MSG_ERROR, "Variable Server could not find variable %s.\n", var_name.c_str());
1✔
103
        _var_info = make_error_ref(var_name);
1✔
104
    } else if ( _var_info->attr ) {
8,054✔
105
        if ( _var_info->attr->type == TRICK_STRUCTURED ) {
8,054✔
106
            // sendErrorMessage("Variable Server: var_add cant add \"%s\" because its a composite variable.\n", var_name);
107
            message_publish(MSG_ERROR, "Variable Server: var_add cant add \"%s\" because its a composite variable.\n", var_name.c_str());
1✔
108

109
            free(_var_info);
1✔
110
            _var_info = make_do_not_resolve_ref(var_name);
1✔
111

112
        } else if ( _var_info->attr->type == TRICK_STL ) {
8,053✔
113
            // sendErrorMessage("Variable Server: var_add cant add \"%s\" because its an STL variable.\n", var_name);
114
            message_publish(MSG_ERROR,"Variable Server: var_add cant add \"%s\" because its an STL variable.\n", var_name.c_str());
1✔
115

116
            free(_var_info);
1✔
117
            _var_info = make_do_not_resolve_ref(var_name);
1✔
118
        }
119
    } else {
120
        // sendErrorMessage("Variable Server: BAD MOJO - Missing ATTRIBUTES.");
121
        message_publish(MSG_ERROR, "Variable Server: BAD MOJO - Missing ATTRIBUTES.");
×
122

123
        free(_var_info);
×
124
        _var_info = make_error_ref(var_name);
×
125
    }
126

127
    // Set up member variables
128
    _var_info->units = NULL;
8,055✔
129
    _address = _var_info->address;
8,055✔
130
    _size = _var_info->attr->size ;
8,055✔
131
    _deref = false;
8,055✔
132

133
    // Deal with weirdness around string vs wstring
134
    _trick_type = _var_info->attr->type ;
8,055✔
135

136
    if ( _var_info->num_index == _var_info->attr->num_index ) {
8,055✔
137
        // single value - nothing else necessary
138
    } else if ( _var_info->attr->index[_var_info->attr->num_index - 1].size != 0 ) {
10✔
139
        // Constrained array
140
        for ( int i = _var_info->attr->num_index-1;  i > _var_info->num_index-1 ; i-- ) {
23✔
141
            _size *= _var_info->attr->index[i].size ;
13✔
142
        }
143
    } else {
144
        // Unconstrained array
145
        if ((_var_info->attr->num_index - _var_info->num_index) > 1 ) {
×
146
            message_publish(MSG_ERROR, "Variable Server Error: var_add(%s) requests more than one dimension of dynamic array.\n", _var_info->reference);
×
147
            message_publish(MSG_ERROR, "Data is not contiguous so returned values are unpredictable.\n") ;
×
148
        }
149
        if ( _var_info->attr->type == TRICK_CHARACTER ) {
×
150
            _trick_type = TRICK_STRING ;
×
151
            _deref = true;
×
152
        } else if ( _var_info->attr->type == TRICK_WCHAR ) {
×
153
            _trick_type = TRICK_WSTRING ;
×
154
            _deref = true;
×
155
        } else {
156
            _deref = true ;
×
157
            _size *= get_size((char*)_address) ;
×
158
        }
159
    }
160
    // handle strings: set a max buffer size, the copy size may vary so will be set in copy_sim_data
161
    if (( _trick_type == TRICK_STRING ) || ( _trick_type == TRICK_WSTRING )) {
8,055✔
162
        _size = MAX_ARRAY_LENGTH ;
6✔
163
    }
164

165
    // Allocate stage and write buffers
166
    _stage_buffer = calloc(_size, 1) ;
8,055✔
167
    _write_buffer = calloc(_size, 1) ;
8,055✔
168

169
    _conversion_factor = cv_get_trivial();
8,055✔
170
    _base_units = _var_info->attr->units;
8,055✔
171
    _requested_units = "";
8,055✔
172
    _name = _var_info->reference;
8,055✔
173

174
    // Done!
175
}
8,055✔
176

177
Trick::VariableReference::~VariableReference() {
55✔
178
    if (_var_info != NULL) {
55✔
179
        free( _var_info );
55✔
180
        _var_info = NULL;
55✔
181
    }
182
    if (_stage_buffer != NULL) {
55✔
183
        free (_stage_buffer);
55✔
184
        _stage_buffer = NULL;
55✔
185
    }
186
    if (_write_buffer != NULL) {
55✔
187
        free (_write_buffer);
55✔
188
        _write_buffer = NULL;
55✔
189
    }
190
    if (_conversion_factor != NULL) {
55✔
191
        cv_free(_conversion_factor);
55✔
192
    }
193
}
55✔
194

195
std::string Trick::VariableReference::getName() const {
12,021✔
196
    return _name;
12,021✔
197
}
198

199
int Trick::VariableReference::getSizeBinary() const {
4,000✔
200
    return _size;
4,000✔
201
}
202

203
TRICK_TYPE Trick::VariableReference::getType() const {
3✔
204
    return _trick_type;
3✔
205
}
206

207
std::string Trick::VariableReference::getBaseUnits() const {
12✔
208
    return _base_units;
12✔
209
}
210

211
int Trick::VariableReference::setRequestedUnits(std::string units_name) {
10✔
212
    // Some error logging lambdas - these should probably go somewhere else
213
    // But I do kinda like them
214
    auto publish = [](MESSAGE_TYPE type, const std::string& message) {
2✔
215
        std::ostringstream oss;
2✔
216
        oss << "Variable Server: " << message << std::endl;
2✔
217
        message_publish(type, oss.str().c_str());
2✔
218
    };
2✔
219

220
    auto publishError = [&](const std::string& units) {
1✔
221
        std::ostringstream oss;
1✔
222
        oss << "units error for [" << getName() << "] [" << units << "]";
1✔
223
        publish(MSG_ERROR, oss.str());
1✔
224
    };
1✔
225

226
    // If the units_name parameter is "xx", set it to the current units.
227
    if (!units_name.compare("xx")) {
10✔
228
        units_name = getBaseUnits();
×
229
    }
230

231
    // Don't try to convert units for a bad ref
232
    if (_var_info->address == &_bad_ref_int) {
10✔
NEW
233
        return -1 ;
×
234
    }
235

236
    // if unitless ('--') then do not convert to udunits 
237
    if (units_name.compare("--")) {
10✔
238
        // Check to see if this is an old style Trick unit that needs to be converted to new udunits
239
        std::string new_units = map_trick_units_to_udunits(units_name) ;
10✔
240
        // Warn if a conversion has taken place
241
        if ( units_name.compare(new_units) ) {
10✔
242
            // TODO: MAKE BETTER SYSTEM FOR ERROR LOGGING
243
            std::ostringstream oss;
×
244
            oss << "[" << getName() << "] old-style units converted from ["
×
245
                << units_name << "] to [" << new_units << "]";
×
246
            publish(MSG_WARNING, oss.str());
×
247
        }
248

249
        // Interpret base unit
250
        ut_unit * from = ut_parse(Trick::UdUnits::get_u_system(), getBaseUnits().c_str(), UT_ASCII) ;
10✔
251
        if ( !from ) {
10✔
252
            std::cout << "Error in interpreting base units" << std::endl;
×
253
            publishError(getBaseUnits());
×
254
            ut_free(from) ;
×
255
            return -1 ;
×
256
        }
257

258
        // Interpret requested unit
259
        ut_unit * to = ut_parse(Trick::UdUnits::get_u_system(), new_units.c_str(), UT_ASCII) ;
10✔
260
        if ( !to ) {
10✔
261
            std::cout << "Error in interpreting requested units" << std::endl;
1✔
262
            publishError(new_units);
1✔
263
            ut_free(from) ;
1✔
264
            ut_free(to) ;
1✔
265
            return -1 ;
1✔
266
        }
267

268
        // Create a converter from the base to the requested
269
        auto new_conversion_factor = ut_get_converter(from, to) ;
9✔
270
        ut_free(from) ;
9✔
271
        ut_free(to) ;
9✔
272
        if ( !new_conversion_factor ) {
9✔
273
            std::ostringstream oss;
1✔
274
            oss << "[" << getName() << "] cannot convert units from [" << getBaseUnits()
1✔
275
                << "] to [" << new_units << "]";
1✔
276
            publish(MSG_ERROR, oss.str());
1✔
277
            return -1 ;
1✔
278
        } else {
279
            _conversion_factor = new_conversion_factor;
8✔
280
        }
281
    
282
        // Set the requested units. This will cause the unit string to be printed in write_value_ascii
283
        _requested_units = new_units;
8✔
284
    }
285
    return 0;
8✔
286
}
287

288
int Trick::VariableReference::stageValue(bool validate_address) {
8,039✔
289
    _write_ready = false;
8,039✔
290

291
    // Copy <size> bytes from <address> to staging_point.
292

293
    // Try to recreate connection if it has been broken
294
    if (_var_info->address == &_bad_ref_int) {
8,039✔
295
        REF2 *new_ref = ref_attributes(_var_info->reference);
1✔
296
        if (new_ref != NULL) {
1✔
297
            _var_info = new_ref;
×
298
            _address = _var_info->address;
×
299
            // _requested_units = "";
300
        }
301
    }
302

303
    // if there's a pointer somewhere in the address path, follow it in case pointer changed
304
    if ( _var_info->pointer_present == 1 ) {
8,039✔
305
        _address = follow_address_path(_var_info) ;
×
306
        if (_address == NULL) {
×
307
            tagAsInvalid();
×
308
        } else if ( validate_address ) {
×
309
            validate();
×
310
        } else {
311
            _var_info->address = _address ;
×
312
        }
313
    }
314

315
    // if this variable is a string we need to get the raw character string out of it.
316
    if (( _trick_type == TRICK_STRING ) && !_deref) {
8,039✔
317
        std::string * str_ptr = (std::string *)_var_info->address ;
5✔
318
        // Get a pointer to the internal character array
319
        _address = (void *)(str_ptr->c_str()) ;
5✔
320
    }
321

322
    // if this variable itself is a pointer, dereference it
323
    if ( _deref ) {
8,039✔
324
        _address = *(void**)_var_info->address ;
×
325
    }
326

327
    // handle c++ string and char*
328
    if ( _trick_type == TRICK_STRING ) {
8,039✔
329
        if (_address == NULL) {
5✔
330
            _size = 0 ;
×
331
        } else {
332
            _size = strlen((char*)_address) + 1 ;
5✔
333
        }
334
    }
335
    // handle c++ wstring and wchar_t*
336
    if ( _trick_type == TRICK_WSTRING ) {
8,039✔
337
        if (_address == NULL) {
×
338
            _size = 0 ;
×
339
        } else {
340
            _size = wcslen((wchar_t *)_address) * sizeof(wchar_t);
×
341
        }
342
    }
343
    if(_address != NULL) {
8,039✔
344
        memcpy( _stage_buffer , _address , _size ) ;
8,039✔
345
    }
346

347
    _staged = true;
8,039✔
348
    return 0;
8,039✔
349
}
350

351
bool Trick::VariableReference::validate() {
3✔
352
    // The address is not NULL.
353
    // Should be called by VariableServer Session if validateAddress is on.
354
    // check the memory manager if the address falls into
355
    // any of the memory blocks it knows of.  Don't do this if we have a std::string or
356
    // wstring type, or we already are pointing to a bad ref.
357
    if ( (_trick_type != TRICK_STRING) and
9✔
358
            (_trick_type != TRICK_WSTRING) and
3✔
359
            (_var_info->address != &_bad_ref_int) and
8✔
360
            (get_alloc_info_of(_address) == NULL) ) {
2✔
361
        
362
        // This variable is broken, make it into an error ref
363
        tagAsInvalid();
1✔
364
        return false;
1✔
365
    }
366

367
    // Everything is fine
368
    return true;
2✔
369
}
370

371
static void write_escaped_string( std::ostream& os, const char* s) {
4✔
372
    for (int ii=0 ; ii<strlen(s) ; ii++) {
41✔
373
        if (isprint(s[ii])) {
37✔
374
            os << s[ii];
29✔
375
        } else {
376
            switch ((s)[ii]) {
8✔
377
                case '\n': os << "\\n"; break;
2✔
378
                case '\t': os << "\\t"; break;
1✔
379
                case '\b': os << "\\b"; break;
1✔
380
                case '\a': os << "\\a"; break;
1✔
381
                case '\f': os << "\\f"; break;
1✔
382
                case '\r': os << "\\n"; break;
1✔
383
                case '\v': os << "\\v"; break;
1✔
384
                case '\"': os << "\\\""; break;
×
385
                default  : {
×
386
                    // Replicating behavior from original vs_format_ascii
387
                    char temp_s[6];
388
                    sprintf(temp_s, "\\x%02x", s[ii]);
×
389
                    os << temp_s ; 
×
390
                    break;
×
391
                }
392
            }
393
        }
394
    }
395
}
4✔
396

397
int Trick::VariableReference::getSizeAscii() const {
×
398
    std::stringstream ss;
×
399
    writeValueAscii(ss);
×
400
    return ss.str().length();
×
401
}
402

403

404
int Trick::VariableReference::writeValueAscii( std::ostream& out ) const {
4,030✔
405
    // This is copied and modified from vs_format_ascii
406

407
    if (!isWriteReady()) {
4,030✔
408
        return -1;
1✔
409
    }
410

411
    int bytes_written = 0;
4,029✔
412
    void * buf_ptr = _write_buffer ;
4,029✔
413
    while (bytes_written < _size) {
8,062✔
414
        bytes_written += _var_info->attr->size ;
4,033✔
415

416
        switch (_trick_type) {
4,033✔
417

418
        case TRICK_CHARACTER:
2✔
419
            if (_var_info->attr->num_index == _var_info->num_index) {
2✔
420
                // Single char
421
                out << (int)cv_convert_double(_conversion_factor, *(char *)buf_ptr);
1✔
422
            } else {
423
                // All but last dim specified, leaves a char array 
424
                write_escaped_string(out, (const char *) buf_ptr);
1✔
425
                bytes_written = _size ;
1✔
426
            }
427
            break;
2✔
428
        case TRICK_UNSIGNED_CHARACTER:
2✔
429
            if (_var_info->attr->num_index == _var_info->num_index) {
2✔
430
                // Single char
431
                out << (unsigned int)cv_convert_double(_conversion_factor,*(unsigned char *)buf_ptr);
1✔
432
            } else {
433
                // All but last dim specified, leaves a char array 
434
                write_escaped_string(out, (const char *) buf_ptr);
1✔
435
                bytes_written = _size ;
1✔
436
            }
437
            break;
2✔
438

439
        case TRICK_WCHAR:{
2✔
440
                if (_var_info->attr->num_index == _var_info->num_index) {
2✔
441
                    out << *(wchar_t *) buf_ptr;
1✔
442
                } else {
443
                    // convert wide char string char string
444
                    size_t len = wcs_to_ncs_len((wchar_t *)buf_ptr) + 1 ;
2✔
445

446
                    char temp_buf[len];
1✔
447
                    wcs_to_ncs((wchar_t *) buf_ptr, temp_buf, len);
1✔
448
                    out << temp_buf;
1✔
449
                    bytes_written = _size ;
2✔
450
                }
451
            }
452
            break;
2✔
453

454
        case TRICK_STRING:
2✔
455
            if ((char *) buf_ptr != NULL) {
2✔
456
                write_escaped_string(out, (const char *) buf_ptr);
2✔
457
                bytes_written = _size ;
2✔
458
            } else {
459
                out << '\0';
×
460
            }
461
            break;
2✔
462

463
        case TRICK_WSTRING:
×
464
            if ((wchar_t *) buf_ptr != NULL) {
×
465
                // convert wide char string char string
466
                size_t len = wcs_to_ncs_len( (wchar_t *)buf_ptr) + 1 ;
×
467

468
                char temp_buf[len];
×
469
                wcs_to_ncs(  (wchar_t *) buf_ptr, temp_buf, len);
×
470
                out << temp_buf;
×
471
                bytes_written = _size ;
×
472
            } else {
473
                out << '\0';
×
474
            }
475
            break;
×
476
        case TRICK_SHORT:
1✔
477
            out << (short)cv_convert_double(_conversion_factor,*(short *)buf_ptr);
1✔
478
            break;
1✔
479

480
        case TRICK_UNSIGNED_SHORT:
×
481
            out << (unsigned short)cv_convert_double(_conversion_factor,*(unsigned short *)buf_ptr);
×
482
            break;
×
483

484
        case TRICK_INTEGER:
4,011✔
485
        case TRICK_ENUMERATED:
486
            out << (int)cv_convert_double(_conversion_factor,*(int *)buf_ptr);
4,011✔
487
            break;
4,011✔
488

489
        case TRICK_BOOLEAN:
1✔
490
            out << (int)cv_convert_double(_conversion_factor,*(bool *)buf_ptr);
1✔
491
            break;
1✔
492

493
        case TRICK_BITFIELD:
×
494
            out << (GET_BITFIELD(buf_ptr, _var_info->attr->size, _var_info->attr->index[0].start, _var_info->attr->index[0].size));
×
495
            break;
×
496

497
        case TRICK_UNSIGNED_BITFIELD:
×
498
            out << (GET_UNSIGNED_BITFIELD(buf_ptr, _var_info->attr->size, _var_info->attr->index[0].start, _var_info->attr->index[0].size));
×
499
            break;
×
500
            
501
        case TRICK_UNSIGNED_INTEGER:
×
502
            out << (unsigned int)cv_convert_double(_conversion_factor,*(unsigned int *)buf_ptr);
×
503
            break;
×
504

505
        case TRICK_LONG: {
1✔
506
            long l = *(long *)buf_ptr;
1✔
507
            if (_conversion_factor != cv_get_trivial()) {
1✔
508
                l = (long)cv_convert_double(_conversion_factor, l);
1✔
509
            }
510
            out << l;
1✔
511
            break;
1✔
512
        }
513

514
        case TRICK_UNSIGNED_LONG: {
1✔
515
            unsigned long ul = *(unsigned long *)buf_ptr;
1✔
516
            if (_conversion_factor != cv_get_trivial()) {
1✔
517
                ul = (unsigned long)cv_convert_double(_conversion_factor, ul);
1✔
518
            }
519
            out << ul;
1✔
520
            break;
1✔
521
        }
522

523
        case TRICK_FLOAT:
×
524
            out << std::setprecision(8) << cv_convert_float(_conversion_factor,*(float *)buf_ptr);
×
525
            break;
×
526

527
        case TRICK_DOUBLE:
5✔
528
            out << std::setprecision(16) << cv_convert_double(_conversion_factor,*(double *)buf_ptr);
5✔
529
            break;
5✔
530

531
        case TRICK_LONG_LONG: {
1✔
532
            long long ll = *(long long *)buf_ptr;
1✔
533
            if (_conversion_factor != cv_get_trivial()) {
1✔
534
                ll = (long long)cv_convert_double(_conversion_factor, ll);
1✔
535
            }
536
            out << ll;
1✔
537
            break;
1✔
538
        }
539

540
        case TRICK_UNSIGNED_LONG_LONG: {
1✔
541
            unsigned long long ull = *(unsigned long long *)buf_ptr;
1✔
542
            if (_conversion_factor != cv_get_trivial()) {
1✔
543
                ull = (unsigned long long)cv_convert_double(_conversion_factor, ull);
1✔
544
            }
545
            out << ull;
1✔
546
            break;
1✔
547
        }
548

549
        case TRICK_NUMBER_OF_TYPES:
3✔
550
            out << "BAD_REF";
3✔
551
            break;
3✔
552

553
        default:{
×
554

555
            break;
×
556
        }
557
        } // end switch
558

559
        if (bytes_written < _size) {
4,033✔
560
        // if returning an array, continue array as comma separated values
561
            out << ",";
4✔
562
            buf_ptr = (void*) ((long)buf_ptr + _var_info->attr->size) ;
4✔
563
        }
564
    } //end while
565

566
    if (_requested_units != "") {
4,029✔
567
        if ( _var_info->attr->mods & TRICK_MODS_UNITSDASHDASH ) {
8✔
568
            out << " {--}";
×
569
        } else {
570
            out << " {" << _requested_units << "}";
8✔
571
        }
572
    }
573

574
    return 0;
4,029✔
575
}
576

577
void Trick::VariableReference::tagAsInvalid () {
2✔
578
    std::string save_name(getName()) ;
2✔
579
    free(_var_info) ;
2✔
580
    _var_info = make_error_ref(save_name) ;
2✔
581
    _address = _var_info->address ;
2✔
582
}
2✔
583

584

585
int Trick::VariableReference::prepareForWrite() {
8,039✔
586
    if (!_staged) {
8,039✔
587
        return 1;
1✔
588
    }
589

590
    void * temp_p = _stage_buffer;
8,038✔
591
    _stage_buffer = _write_buffer;
8,038✔
592
    _write_buffer = temp_p;
8,038✔
593

594
    _staged = false;
8,038✔
595
    _write_ready = true;
8,038✔
596
    return 0;
8,038✔
597
}
598

599
bool Trick::VariableReference::isStaged() const {
8,003✔
600
    return _staged;
8,003✔
601
}
602

603
bool Trick::VariableReference::isWriteReady() const {
4,035✔
604
    return _write_ready;
4,035✔
605
}
606

607
int Trick::VariableReference::writeTypeBinary( std::ostream& out, bool byteswap ) const {
4,000✔
608
    int local_type = _trick_type;
4,000✔
609
    if (byteswap) {
4,000✔
610
        local_type = trick_byteswap_int(local_type);
×
611
    }
612
    out.write(const_cast<const char *>(reinterpret_cast<char *>(&local_type)), sizeof(int));
4,000✔
613

614
    return 0;
4,000✔
615
}
616

617
int Trick::VariableReference::writeSizeBinary( std::ostream& out, bool byteswap ) const {
4,000✔
618
    int local_size = _size;
4,000✔
619
    if (byteswap) {
4,000✔
620
        local_size = trick_byteswap_int(local_size);
×
621
    }
622
    out.write(const_cast<const char *>(reinterpret_cast<char *>(&local_size)), sizeof(int));
4,000✔
623

624
    return 0;
4,000✔
625
}
626

627
int Trick::VariableReference::writeNameBinary( std::ostream& out, bool byteswap ) const {
4,001✔
628
    std::string name = getName();
4,001✔
629
    out.write(name.c_str(), name.size());
4,001✔
630

631
    return 0;
8,002✔
632
}
633

634
int Trick::VariableReference::writeNameLengthBinary( std::ostream& out, bool byteswap ) const {
4,001✔
635
    int name_size = getName().size();
4,001✔
636
    if (byteswap) {
4,001✔
637
        name_size = trick_byteswap_int(name_size);
×
638
    }
639

640
    out.write(const_cast<const char *>(reinterpret_cast<char *>(&name_size)), sizeof(int));
4,001✔
641

642
    return 0;
4,001✔
643
}
644

645

646
void Trick::VariableReference::byteswap_var (char * out, char * in) const {
1✔
647
    byteswap_var(out, in, *this);
1✔
648
}
1✔
649

650

651
void Trick::VariableReference::byteswap_var (char * out, char * in, const VariableReference& ref) {
9✔
652
    ATTRIBUTES * attr = ref._var_info->attr;
9✔
653
    int array_size = 1;
9✔
654

655
    // Determine how many elements are in this array if it is an array
656
    for (int j = 0; j < ref._var_info->attr->num_index; j++) {
16✔
657
        array_size *= attr->index[j].size;
7✔
658
    }
659

660
    switch (attr->size) {
9✔
661
        case 1:
2✔
662
            // If these are just characters, no need to byteswap
663
            for (int j = 0; j < array_size; j++) {
10✔
664
                out[j] = in[j];
8✔
665
            }
666
            break;
2✔
667

668
        case 2: {
1✔
669
            short * short_in = reinterpret_cast<short *> (in);
1✔
670
            short * short_out = reinterpret_cast<short *> (out);
1✔
671

672
            for (int j = 0; j < array_size; j++) {
2✔
673
                short_out[j] = trick_byteswap_short(short_in[j]);
1✔
674
            }
675
            break;
1✔
676
        }
677

678
        case 4: {
4✔
679
            int * int_in = reinterpret_cast<int *> (in);
4✔
680
            int * int_out = reinterpret_cast<int *> (out);
4✔
681

682
            for (int j = 0; j < array_size; j++) {
131✔
683
                int_out[j] = trick_byteswap_int(int_in[j]);
127✔
684
            }
685
            break;
4✔
686
        }
687
        case 8: {
2✔
688
            // We don't actually care if this is double or long, just that it's the right size
689
            double * double_in = reinterpret_cast<double *> (in);
2✔
690
            double * double_out = reinterpret_cast<double *> (out);
2✔
691

692
            for (int j = 0; j < array_size; j++) {
8✔
693
                double_out[j] = trick_byteswap_double(double_in[j]);
6✔
694
            }
695
            break;
2✔
696
        }
697
    }
698
}
9✔
699

700

701

702
int Trick::VariableReference::writeValueBinary( std::ostream& out, bool byteswap ) const {
4,006✔
703

704
    if ( _trick_type == TRICK_BITFIELD ) {
4,006✔
705
        int temp_i = GET_BITFIELD(_write_buffer , _var_info->attr->size ,
×
706
            _var_info->attr->index[0].start, _var_info->attr->index[0].size) ;
707
        out.write((char *)(&temp_i), _size);
×
708
        return _size;
×
709
    }
710

711
    if ( _trick_type == TRICK_UNSIGNED_BITFIELD ) {
4,006✔
712
        int temp_unsigned = GET_UNSIGNED_BITFIELD(_write_buffer , _var_info->attr->size ,
×
713
                _var_info->attr->index[0].start, _var_info->attr->index[0].size) ;
714
        out.write((char *)(&temp_unsigned), _size);
×
715
        return _size;
×
716
    }
717

718
    if (_trick_type ==  TRICK_NUMBER_OF_TYPES) {
4,006✔
719
        // TRICK_NUMBER_OF_TYPES is an error case
720
        int temp_zero = 0 ;
×
721
        out.write((char *)(&temp_zero), _size);
×
722
        return _size;
×
723
    }
724

725
    if (byteswap) {
4,006✔
726
        char * byteswap_buf = (char *) calloc (_size, 1);
1✔
727
        byteswap_var(byteswap_buf, (char *) _write_buffer);
1✔
728
        out.write(byteswap_buf, _size);
1✔
729
        free (byteswap_buf);
1✔
730
    }
731
    else {
732
        out.write((char *) _write_buffer, _size);
4,005✔
733
    }
734

735
    return _size;
4,006✔
736
    
737
}  
738

739
std::ostream& Trick::operator<< (std::ostream& s, const Trick::VariableReference& ref) {
6✔
740
    s << "      \"" << ref.getName() << "\"";
6✔
741
    return s;
6✔
742
}
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

© 2026 Coveralls, Inc