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

nasa / trick / 38950168522

16 Oct 2026 06:48PM UTC coverage: 56.879% (-0.005%) from 56.884%
38950168522

Pull #2225

github

web-flow
Merge f77fc6e50 into e101223ed
Pull Request #2225: fix: Resolve compilation warnings

5 of 32 new or added lines in 9 files covered. (15.63%)

14978 of 26333 relevant lines covered (56.88%)

483764.74 hits per line

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

76.54
/trick_source/sim_services/VariableServer/VariableReference.cpp
1
#include "trick/VariableReference.hh"
2

3
#include "trick/ReferenceUtils.hh"
4
#include "trick/UdUnits.hh"
5
#include "trick/bitfield_proto.h"
6
#include "trick/map_trick_units_to_udunits.hh"
7
#include "trick/memorymanager_c_intf.h"
8
#include "trick/message_proto.h"
9
#include "trick/message_type.h"
10
#include "trick/trick_byteswap.h"
11
#include "trick/wcs_ext.h"
12

13
#include <iomanip> // for setprecision
14
#include <iostream>
15
#include <math.h> // for fpclassify
16
#include <sstream>
17
#include <stdlib.h>
18
#include <string.h>
19
#include <udunits2.h>
20
#include <vector>
21

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

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

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

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

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

71
    _var_info = make_time_ref(time);
×
72

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

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

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

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

91
Trick::VariableReference::VariableReference(std::string var_name) : _staged(false), _write_ready(false) {
8,491 ✔
92

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

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

111
            free(_var_info);
1 ✔
112
            _var_info = make_do_not_resolve_ref(var_name);
1 ✔
113
        }
114
    } else {
115
        // sendErrorMessage("Variable Server: BAD MOJO - Missing ATTRIBUTES.");
116
        message_publish(MSG_ERROR, "Variable Server: BAD MOJO - Missing ATTRIBUTES.");
×
117

118
        free(_var_info);
×
119
        _var_info = make_error_ref(var_name);
×
120
    }
121

122
    // Set up member variables
123
    _var_info->units = NULL;
8,491 ✔
124
    _address = _var_info->address;
8,491 ✔
125
    _size = _var_info->attr->size ;
8,491 ✔
126
    _deref = false;
8,491 ✔
127

128
    // Use ReferenceUtils for STL-aware type and size resolution.
129
    // Handles cases such as: vec[0], xxx[2].yyy.zzz[3].www, xxx[2].yyy.zzz[3].aaa[0]
130
    _trick_type        = Trick::ReferenceUtils::effective_trick_type(_var_info);
8,491 ✔
131
    _used_stl_indexing = Trick::ReferenceUtils::is_stl_ref(_var_info);
8,491 ✔
132

133
    if (_used_stl_indexing)
8,491 ✔
134
    {
135
        // effective_trick_size returns the correct element byte size for every STL case
136
        _size = (int)Trick::ReferenceUtils::effective_trick_size(_var_info);
81 ✔
137
        // address already points to the correct element from ref_dim; treat as single value
138
    }
139
    else
140
    {
141
        // Non-STL: apply the original array dimension size calculation
142
        if ( _var_info->num_index == _var_info->attr->num_index ) {
8,410 ✔
143
            // single value - nothing else necessary
144
        } else if ( _var_info->attr->index[_var_info->attr->num_index - 1].size != 0 ) {
10 ✔
145
            // Constrained array
146
            for ( int i = _var_info->attr->num_index-1;  i > _var_info->num_index-1 ; i-- ) {
23 ✔
147
                _size *= _var_info->attr->index[i].size ;
13 ✔
148
            }
149
        } else {
150
            // Unconstrained array
151
            if ((_var_info->attr->num_index - _var_info->num_index) > 1 ) {
×
152
                message_publish(MSG_ERROR, "Variable Server Error: var_add(%s) requests more than one dimension of dynamic array.\n", _var_info->reference);
×
153
                message_publish(MSG_ERROR, "Data is not contiguous so returned values are unpredictable.\n") ;
×
154
            }
155
            if ( _var_info->attr->type == TRICK_CHARACTER ) {
×
156
                _trick_type = TRICK_STRING ;
×
157
                _deref = true;
×
158
            } else if ( _var_info->attr->type == TRICK_WCHAR ) {
×
159
                _trick_type = TRICK_WSTRING ;
×
160
                _deref = true;
×
161
            } else {
162
                _deref = true ;
×
163
                _size *= get_size((char*)_address) ;
×
164
            }
165
        }
166
    }
167
    // handle strings: set a max buffer size, the copy size may vary so will be set in copy_sim_data
168
    if (( _trick_type == TRICK_STRING ) || ( _trick_type == TRICK_WSTRING )) {
8,491 ✔
169
        _size = MAX_ARRAY_LENGTH ;
26 ✔
170
    }
171

172
    // Allocate stage and write buffers
173
    _stage_buffer = calloc(_size, 1) ;
8,491 ✔
174
    _write_buffer = calloc(_size, 1) ;
8,491 ✔
175

176
    _conversion_factor = cv_get_trivial();
8,491 ✔
177
    _base_units = _var_info->attr->units;
8,491 ✔
178
    _requested_units = "";
8,491 ✔
179
    _name = _var_info->reference;
8,491 ✔
180

181
    // Done!
182
}
8,491 ✔
183

184
Trick::VariableReference::~VariableReference() {
488 ✔
185
    if (_var_info != NULL) {
488 ✔
186
        free( _var_info );
488 ✔
187
        _var_info = NULL;
488 ✔
188
    }
189
    if (_stage_buffer != NULL) {
488 ✔
190
        free (_stage_buffer);
488 ✔
191
        _stage_buffer = NULL;
488 ✔
192
    }
193
    if (_write_buffer != NULL) {
488 ✔
194
        free (_write_buffer);
488 ✔
195
        _write_buffer = NULL;
488 ✔
196
    }
197
    if (_conversion_factor != NULL) {
488 ✔
198
        cv_free(_conversion_factor);
488 ✔
199
    }
200
}
488 ✔
201

202
std::string Trick::VariableReference::getName() const {
12,037 ✔
203
    return _name;
12,037 ✔
204
}
205

206
int Trick::VariableReference::getSizeBinary() const {
4,000 ✔
207
    return _size;
4,000 ✔
208
}
209

210
TRICK_TYPE Trick::VariableReference::getType() const {
4 ✔
211
    return _trick_type;
4 ✔
212
}
213

214
std::string Trick::VariableReference::getBaseUnits() const {
26 ✔
215
    return _base_units;
26 ✔
216
}
217

218
int Trick::VariableReference::setRequestedUnits(std::string units_name) {
17 ✔
219
    // Some error logging lambdas - these should probably go somewhere else
220
    // But I do kinda like them
221
    auto publish = [](MESSAGE_TYPE type, const std::string& message) {
2 ✔
222
        std::ostringstream oss;
2 ✔
223
        oss << "Variable Server: " << message << std::endl;
2 ✔
224
        message_publish(type, oss.str().c_str());
2 ✔
225
    };
2 ✔
226

227
    auto publishError = [&](const std::string& units) {
1 ✔
228
        std::ostringstream oss;
1 ✔
229
        oss << "units error for [" << getName() << "] [" << units << "]";
1 ✔
230
        publish(MSG_ERROR, oss.str());
1 ✔
231
    };
1 ✔
232

233
    // If the units_name parameter is "xx", set it to the current units.
234
    if (!units_name.compare("xx")) {
17 ✔
235
        units_name = getBaseUnits();
7 ✔
236
    }
237

238
    // Don't try to convert units for a bad ref
239
    if (_var_info->address == &_bad_ref_int) {
17 ✔
240
        return -1 ;
×
241
    }
242

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

256
        // Interpret base unit
257
        ut_unit * from = ut_parse(Trick::UdUnits::get_u_system(), getBaseUnits().c_str(), UT_ASCII) ;
17 ✔
258
        if ( !from ) {
17 ✔
259
            std::cout << "Error in interpreting base units" << std::endl;
×
260
            publishError(getBaseUnits());
×
261
            ut_free(from) ;
×
262
            return -1 ;
×
263
        }
264

265
        // Interpret requested unit
266
        ut_unit * to = ut_parse(Trick::UdUnits::get_u_system(), new_units.c_str(), UT_ASCII) ;
17 ✔
267
        if ( !to ) {
17 ✔
268
            std::cout << "Error in interpreting requested units" << std::endl;
1 ✔
269
            publishError(new_units);
1 ✔
270
            ut_free(from) ;
1 ✔
271
            ut_free(to) ;
1 ✔
272
            return -1 ;
1 ✔
273
        }
274

275
        // Create a converter from the base to the requested
276
        auto new_conversion_factor = ut_get_converter(from, to) ;
16 ✔
277
        ut_free(from) ;
16 ✔
278
        ut_free(to) ;
16 ✔
279
        if ( !new_conversion_factor ) {
16 ✔
280
            std::ostringstream oss;
1 ✔
281
            oss << "[" << getName() << "] cannot convert units from [" << getBaseUnits()
1 ✔
282
                << "] to [" << new_units << "]";
1 ✔
283
            publish(MSG_ERROR, oss.str());
1 ✔
284
            return -1 ;
1 ✔
285
        } else {
1 ✔
286
            _conversion_factor = new_conversion_factor;
15 ✔
287
        }
288
    
289
        // Set the requested units. This will cause the unit string to be printed in write_value_ascii
290
        _requested_units = new_units;
15 ✔
291
    }
17 ✔
292
    return 0;
15 ✔
293
}
294

295
int Trick::VariableReference::stageValue(bool validate_address) {
8,474 ✔
296
    _write_ready = false;
8,474 ✔
297

298
    // Copy <size> bytes from <address> to staging_point.
299

300
    // Try to recreate connection if it has been broken
301
    if (_var_info->address == &_bad_ref_int) {
8,474 ✔
302
        REF2 *new_ref = ref_attributes(_var_info->reference);
171 ✔
303
        if (new_ref != NULL) {
171 ✔
304
            _var_info = new_ref;
×
305
            _address = _var_info->address;
×
306
            // _requested_units = "";
307
        }
308
    }
309

310
    // if there's a pointer somewhere in the address path, follow it in case pointer changed
311
    // BUT: if we've indexed into an STL container, then the address already points to the correct location
312
    // and follow_address_path would incorrectly recalculate it (it doesn't understand STL indexing)
313
    // Use the _used_stl_indexing flag that was set during construction when we detected STL indexing
314
    // (when num_index > attr->num_index and attr->type == TRICK_STL)
315
    if ( _var_info->pointer_present == 1 && !_used_stl_indexing ) {
8,474 ✔
316
        _address = follow_address_path(_var_info) ;
180 ✔
317
        if (_address == NULL) {
180 ✔
318
            tagAsInvalid();
×
319
        } else if ( validate_address ) {
180 ✔
320
            validate();
×
321
        } else {
322
            _var_info->address = _address ;
180 ✔
323
        }
324
    }
325

326
    // if this variable is a string we need to get the raw character string out of it.
327
    if (( _trick_type == TRICK_STRING ) && !_deref) {
8,474 ✔
328
        std::string * str_ptr = (std::string *)_var_info->address ;
25 ✔
329
        // Get a pointer to the internal character array
330
        _address = (void *)(str_ptr->c_str()) ;
25 ✔
331
    }
332

333
    // if this variable is a wstring we need to get the raw wide character string out of it.
334
    if ((_trick_type == TRICK_WSTRING) && !_deref)
8,474 ✔
335
    {
336
        std::wstring *wstr_ptr = (std::wstring *)_var_info->address;
×
337
        // Get a pointer to the internal wide character array
338
        _address = (void *)(wstr_ptr->c_str());
×
339
    }
340

341
    // if this variable itself is a pointer, dereference it
342
    if ( _deref ) {
8,474 ✔
343
        _address = *(void**)_var_info->address ;
×
344
    }
345

346
    // handle c++ string and char*
347
    if ( _trick_type == TRICK_STRING ) {
8,474 ✔
348
        if (_address == NULL) {
25 ✔
349
            _size = 0 ;
×
350
        } else {
351
            _size = strlen((char*)_address) + 1 ;
25 ✔
352
        }
353
    }
354
    // handle c++ wstring and wchar_t*
355
    if ( _trick_type == TRICK_WSTRING ) {
8,474 ✔
356
        if (_address == NULL) {
×
357
            _size = 0 ;
×
358
        } else {
359
            _size = (wcslen((wchar_t *)_address) + 1) * sizeof(wchar_t);
×
360
        }
361
    }
362
    if(_address != NULL) {
8,474 ✔
363
        memcpy( _stage_buffer , _address , _size ) ;
8,474 ✔
364
    }
365

366
    _staged = true;
8,474 ✔
367
    return 0;
8,474 ✔
368
}
369

370
bool Trick::VariableReference::validate() {
3 ✔
371
    // The address is not NULL.
372
    // Should be called by VariableServer Session if validateAddress is on.
373
    // check the memory manager if the address falls into
374
    // any of the memory blocks it knows of.  Don't do this if we have a std::string or
375
    // wstring type, or we already are pointing to a bad ref.
376
    if ( (_trick_type != TRICK_STRING) and
9 ✔
377
            (_trick_type != TRICK_WSTRING) and
3 ✔
378
            (_var_info->address != &_bad_ref_int) and
8 ✔
379
            (get_alloc_info_of(_address) == NULL) ) {
2 ✔
380
        
381
        // This variable is broken, make it into an error ref
382
        tagAsInvalid();
1 ✔
383
        return false;
1 ✔
384
    }
385

386
    // Everything is fine
387
    return true;
2 ✔
388
}
389

390
static void write_escaped_string( std::ostream& os, const char* s) {
24 ✔
391
    for (int ii=0 ; ii<strlen(s) ; ii++) {
226 ✔
392
        if (isprint(s[ii])) {
202 ✔
393
            os << s[ii];
194 ✔
394
        } else {
395
            switch ((s)[ii]) {
8 ✔
396
                case '\n': os << "\\n"; break;
2 ✔
397
                case '\t': os << "\\t"; break;
1 ✔
398
                case '\b': os << "\\b"; break;
1 ✔
399
                case '\a': os << "\\a"; break;
1 ✔
400
                case '\f': os << "\\f"; break;
1 ✔
401
                case '\r': os << "\\n"; break;
1 ✔
402
                case '\v': os << "\\v"; break;
1 ✔
403
                case '\"': os << "\\\""; break;
×
404
                default  : {
×
405
                    // Replicating behavior from original vs_format_ascii
406
                    char temp_s[6];
NEW
407
                    snprintf(temp_s, sizeof(temp_s), "\\x%02x", s[ii]);
×
408
                    os << temp_s ; 
×
409
                    break;
×
410
                }
411
            }
412
        }
413
    }
414
}
24 ✔
415

416
int Trick::VariableReference::getSizeAscii() const {
×
417
    std::stringstream ss;
×
418
    writeValueAscii(ss);
×
419
    return ss.str().length();
×
420
}
×
421

422

423
int Trick::VariableReference::writeValueAscii( std::ostream& out ) const {
4,465 ✔
424
    // This is copied and modified from vs_format_ascii
425

426
    if (!isWriteReady()) {
4,465 ✔
427
        return -1;
1 ✔
428
    }
429

430
    // local_type is set to the type of the attribute, but if it's a STL type, we need to use the element type.
431
    TRICK_TYPE local_type = _trick_type;
4,464 ✔
432

433
    if (_trick_type == TRICK_STL) {
4,464 ✔
434
        // If the variable is an STL type, use the STL element type for writting value
435
        local_type = _var_info->attr->stl_elem_type;
×
436
    }
437

438
    int bytes_written = 0;
4,464 ✔
439
    void * buf_ptr = _write_buffer ;
4,464 ✔
440
    while (bytes_written < _size) {
8,932 ✔
441
        bytes_written += _var_info->attr->size ;
4,468 ✔
442

443
        switch (local_type) {
4,468 ✔
444

445
        case TRICK_CHARACTER:
19 ✔
446
            if (_var_info->attr->num_index == _var_info->num_index) {
19 ✔
447
                // Single char
448
                out << (int)cv_convert_double(_conversion_factor, *(char *)buf_ptr);
18 ✔
449
            } else {
450
                // All but last dim specified, leaves a char array 
451
                write_escaped_string(out, (const char *) buf_ptr);
1 ✔
452
                bytes_written = _size ;
1 ✔
453
            }
454
            break;
19 ✔
455
        case TRICK_UNSIGNED_CHARACTER:
2 ✔
456
            if (_var_info->attr->num_index == _var_info->num_index) {
2 ✔
457
                // Single char
458
                out << (unsigned int)cv_convert_double(_conversion_factor,*(unsigned char *)buf_ptr);
1 ✔
459
            } else {
460
                // All but last dim specified, leaves a char array 
461
                write_escaped_string(out, (const char *) buf_ptr);
1 ✔
462
                bytes_written = _size ;
1 ✔
463
            }
464
            break;
2 ✔
465

466
        case TRICK_WCHAR:{
2 ✔
467
                if (_var_info->attr->num_index == _var_info->num_index) {
2 ✔
468
                    out << *(wchar_t *) buf_ptr;
1 ✔
469
                } else {
470
                    // convert wide char string char string
471
                    size_t len = wcs_to_ncs_len((wchar_t *)buf_ptr) + 1 ;
1 ✔
472

473
                    std::vector<char> temp_buf(len);
1 ✔
474
                    wcs_to_ncs((wchar_t*)buf_ptr, temp_buf.data(), len);
1 ✔
475
                    out << temp_buf.data();
1 ✔
476
                    bytes_written = _size ;
1 ✔
477
                }
1 ✔
478
            }
479
            break;
2 ✔
480

481
        case TRICK_STRING:
22 ✔
482
            if ((char *) buf_ptr != NULL) {
22 ✔
483
                write_escaped_string(out, (const char *) buf_ptr);
22 ✔
484
                bytes_written = _size ;
22 ✔
485
            } else {
486
                out << '\0';
×
487
            }
488
            break;
22 ✔
489

490
        case TRICK_WSTRING:
×
491
            if ((wchar_t *) buf_ptr != NULL) {
×
492
                // convert wide char string char string
493
                size_t len = wcs_to_ncs_len( (wchar_t *)buf_ptr) + 1 ;
×
494

NEW
495
                std::vector<char> temp_buf(len);
×
NEW
496
                wcs_to_ncs((wchar_t*)buf_ptr, temp_buf.data(), len);
×
NEW
497
                out << temp_buf.data();
×
498
                bytes_written = _size ;
×
499
            } else {
×
500
                out << '\0';
×
501
            }
502
            break;
×
503
        case TRICK_SHORT:
14 ✔
504
            out << (short)cv_convert_double(_conversion_factor,*(short *)buf_ptr);
14 ✔
505
            break;
14 ✔
506

507
        case TRICK_UNSIGNED_SHORT:
7 ✔
508
            out << (unsigned short)cv_convert_double(_conversion_factor,*(unsigned short *)buf_ptr);
7 ✔
509
            break;
7 ✔
510

511
        case TRICK_INTEGER:
4,083 ✔
512
        case TRICK_ENUMERATED:
513
            out << (int)cv_convert_double(_conversion_factor,*(int *)buf_ptr);
4,083 ✔
514
            break;
4,083 ✔
515

516
        case TRICK_BOOLEAN:
28 ✔
517
            out << (int)cv_convert_double(_conversion_factor,*(bool *)buf_ptr);
28 ✔
518
            break;
28 ✔
519

520
        case TRICK_BITFIELD:
×
521
            out << (GET_BITFIELD(buf_ptr, _var_info->attr->size, _var_info->attr->index[0].start, _var_info->attr->index[0].size));
×
522
            break;
×
523

524
        case TRICK_UNSIGNED_BITFIELD:
×
525
            out << (GET_UNSIGNED_BITFIELD(buf_ptr, _var_info->attr->size, _var_info->attr->index[0].start, _var_info->attr->index[0].size));
×
526
            break;
×
527
            
528
        case TRICK_UNSIGNED_INTEGER:
8 ✔
529
            out << (unsigned int)cv_convert_double(_conversion_factor,*(unsigned int *)buf_ptr);
8 ✔
530
            break;
8 ✔
531

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

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

550
        case TRICK_FLOAT:
23 ✔
551
            out << std::setprecision(8) << cv_convert_float(_conversion_factor,*(float *)buf_ptr);
23 ✔
552
            break;
23 ✔
553

554
        case TRICK_DOUBLE:
42 ✔
555
            out << std::setprecision(16) << cv_convert_double(_conversion_factor,*(double *)buf_ptr);
42 ✔
556
            break;
42 ✔
557

558
        case TRICK_LONG_LONG: {
16 ✔
559
            long long ll = *(long long *)buf_ptr;
16 ✔
560
            if (_conversion_factor != cv_get_trivial()) {
16 ✔
561
                ll = (long long)cv_convert_double(_conversion_factor, ll);
1 ✔
562
            }
563
            out << ll;
16 ✔
564
            break;
16 ✔
565
        }
566

567
        case TRICK_UNSIGNED_LONG_LONG: {
8 ✔
568
            unsigned long long ull = *(unsigned long long *)buf_ptr;
8 ✔
569
            if (_conversion_factor != cv_get_trivial()) {
8 ✔
570
                ull = (unsigned long long)cv_convert_double(_conversion_factor, ull);
1 ✔
571
            }
572
            out << ull;
8 ✔
573
            break;
8 ✔
574
        }
575

576
        case TRICK_NUMBER_OF_TYPES:
172 ✔
577
            out << "BAD_REF";
172 ✔
578
            break;
172 ✔
579

580
        default:{
×
581

582
            break;
×
583
        }
584
        } // end switch
585

586
        if (bytes_written < _size) {
4,468 ✔
587
        // if returning an array, continue array as comma separated values
588
            out << ",";
4 ✔
589
            buf_ptr = (void*) ((long)buf_ptr + _var_info->attr->size) ;
4 ✔
590
        }
591
    } //end while
592

593
    if (_requested_units != "") {
4,464 ✔
594
        if ( _var_info->attr->mods & TRICK_MODS_UNITSDASHDASH ) {
15 ✔
595
            out << " {--}";
×
596
        } else {
597
            out << " {" << _requested_units << "}";
15 ✔
598
        }
599
    }
600

601
    return 0;
4,464 ✔
602
}
603

604
void Trick::VariableReference::tagAsInvalid () {
2 ✔
605
    std::string save_name(getName()) ;
2 ✔
606
    free(_var_info) ;
2 ✔
607
    _var_info = make_error_ref(save_name) ;
2 ✔
608
    _address = _var_info->address ;
2 ✔
609
}
2 ✔
610

611

612
int Trick::VariableReference::prepareForWrite() {
8,474 ✔
613
    if (!_staged) {
8,474 ✔
614
        return 1;
1 ✔
615
    }
616

617
    void * temp_p = _stage_buffer;
8,473 ✔
618
    _stage_buffer = _write_buffer;
8,473 ✔
619
    _write_buffer = temp_p;
8,473 ✔
620

621
    _staged = false;
8,473 ✔
622
    _write_ready = true;
8,473 ✔
623
    return 0;
8,473 ✔
624
}
625

626
bool Trick::VariableReference::isStaged() const {
8,438 ✔
627
    return _staged;
8,438 ✔
628
}
629

630
bool Trick::VariableReference::isWriteReady() const {
4,470 ✔
631
    return _write_ready;
4,470 ✔
632
}
633

634
int Trick::VariableReference::writeTypeBinary( std::ostream& out, bool byteswap ) const {
4,000 ✔
635
    int local_type = _trick_type;
4,000 ✔
636
    if (byteswap) {
4,000 ✔
637
        local_type = trick_byteswap_int(local_type);
×
638
    }
639
    out.write(const_cast<const char *>(reinterpret_cast<char *>(&local_type)), sizeof(int));
4,000 ✔
640

641
    return 0;
4,000 ✔
642
}
643

644
int Trick::VariableReference::writeSizeBinary( std::ostream& out, bool byteswap ) const {
4,000 ✔
645
    int local_size = _size;
4,000 ✔
646
    if (byteswap) {
4,000 ✔
647
        local_size = trick_byteswap_int(local_size);
×
648
    }
649
    out.write(const_cast<const char *>(reinterpret_cast<char *>(&local_size)), sizeof(int));
4,000 ✔
650

651
    return 0;
4,000 ✔
652
}
653

654
int Trick::VariableReference::writeNameBinary( std::ostream& out, bool byteswap ) const {
4,001 ✔
655
    std::string name = getName();
4,001 ✔
656
    out.write(name.c_str(), name.size());
4,001 ✔
657

658
    return 0;
4,001 ✔
659
}
4,001 ✔
660

661
int Trick::VariableReference::writeNameLengthBinary( std::ostream& out, bool byteswap ) const {
4,001 ✔
662
    int name_size = getName().size();
4,001 ✔
663
    if (byteswap) {
4,001 ✔
664
        name_size = trick_byteswap_int(name_size);
×
665
    }
666

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

669
    return 0;
4,001 ✔
670
}
671

672

673
void Trick::VariableReference::byteswap_var (char * out, char * in) const {
1 ✔
674
    byteswap_var(out, in, *this);
1 ✔
675
}
1 ✔
676

677

678
void Trick::VariableReference::byteswap_var (char * out, char * in, const VariableReference& ref) {
9 ✔
679
    ATTRIBUTES * attr = ref._var_info->attr;
9 ✔
680
    int array_size = 1;
9 ✔
681

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

687
    switch (attr->size) {
9 ✔
688
        case 1:
2 ✔
689
            // If these are just characters, no need to byteswap
690
            for (int j = 0; j < array_size; j++) {
10 ✔
691
                out[j] = in[j];
8 ✔
692
            }
693
            break;
2 ✔
694

695
        case 2: {
1 ✔
696
            short * short_in = reinterpret_cast<short *> (in);
1 ✔
697
            short * short_out = reinterpret_cast<short *> (out);
1 ✔
698

699
            for (int j = 0; j < array_size; j++) {
2 ✔
700
                short_out[j] = trick_byteswap_short(short_in[j]);
1 ✔
701
            }
702
            break;
1 ✔
703
        }
704

705
        case 4: {
4 ✔
706
            int * int_in = reinterpret_cast<int *> (in);
4 ✔
707
            int * int_out = reinterpret_cast<int *> (out);
4 ✔
708

709
            for (int j = 0; j < array_size; j++) {
131 ✔
710
                int_out[j] = trick_byteswap_int(int_in[j]);
127 ✔
711
            }
712
            break;
4 ✔
713
        }
714
        case 8: {
2 ✔
715
            // We don't actually care if this is double or long, just that it's the right size
716
            double * double_in = reinterpret_cast<double *> (in);
2 ✔
717
            double * double_out = reinterpret_cast<double *> (out);
2 ✔
718

719
            for (int j = 0; j < array_size; j++) {
8 ✔
720
                double_out[j] = trick_byteswap_double(double_in[j]);
6 ✔
721
            }
722
            break;
2 ✔
723
        }
724
    }
725
}
9 ✔
726

727

728

729
int Trick::VariableReference::writeValueBinary( std::ostream& out, bool byteswap ) const {
4,006 ✔
730
    // local_type is set to the type of the attribute, but if it's a STL type, we need to use the element type.
731
    TRICK_TYPE local_type = _trick_type;
4,006 ✔
732
    if (local_type == TRICK_STL) {
4,006 ✔
733
        // If the variable is an STL type, use the STL element type for writing value
734
        local_type = _var_info->attr->stl_elem_type;
×
735
    }
736

737
    if ( local_type == TRICK_BITFIELD ) {
4,006 ✔
738
        int temp_i = GET_BITFIELD(_write_buffer , _var_info->attr->size ,
×
739
            _var_info->attr->index[0].start, _var_info->attr->index[0].size) ;
740
        out.write((char *)(&temp_i), _size);
×
741
        return _size;
×
742
    }
743

744
    if ( local_type == TRICK_UNSIGNED_BITFIELD ) {
4,006 ✔
745
        int temp_unsigned = GET_UNSIGNED_BITFIELD(_write_buffer , _var_info->attr->size ,
×
746
                _var_info->attr->index[0].start, _var_info->attr->index[0].size) ;
747
        out.write((char *)(&temp_unsigned), _size);
×
748
        return _size;
×
749
    }
750

751
    if (local_type ==  TRICK_NUMBER_OF_TYPES) {
4,006 ✔
752
        // TRICK_NUMBER_OF_TYPES is an error case
753
        int temp_zero = 0 ;
×
754
        out.write((char *)(&temp_zero), _size);
×
755
        return _size;
×
756
    }
757

758
    if (byteswap) {
4,006 ✔
759
        char * byteswap_buf = (char *) calloc (_size, 1);
1 ✔
760
        byteswap_var(byteswap_buf, (char *) _write_buffer);
1 ✔
761
        out.write(byteswap_buf, _size);
1 ✔
762
        free (byteswap_buf);
1 ✔
763
    }
764
    else {
765
        out.write((char *) _write_buffer, _size);
4,005 ✔
766
    }
767

768
    return _size;
4,006 ✔
769
    
770
}  
771

772
std::ostream& Trick::operator<< (std::ostream& s, const Trick::VariableReference& ref) {
6 ✔
773
    s << "      \"" << ref.getName() << "\"";
6 ✔
774
    return s;
6 ✔
775
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc