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

nasa / trick / 4308414230

pending completion
4308414230

push

github

John M. Penn
Merge branch 'master' of https://github.com/nasa/trick

11841 of 20793 relevant lines covered (56.95%)

83099.68 hits per line

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

93.44
/trick_source/trick_utils/var_binary_parser/src/var_binary_parser.cc
1
#include "trick/var_binary_parser.hh"
2
#include "trick/variable_server_message_types.h"
3
#include <climits>
4
#include <iostream>
5
#include <sstream>
6

7

8
/**************************************************************************
9
 * Var implementation
10
**************************************************************************/
11

12

13
void Var::setName(size_t name_size, const std::vector<unsigned char>& name_data) {
26✔
14
    _has_name = true;
26✔
15
    _name_length = name_size;
26✔
16
    std::stringstream ss;
26✔
17

18
    for (unsigned char character : name_data) {
169✔
19
        ss << static_cast<char>(character);
143✔
20
    }
21

22
    _name = ss.str();
26✔
23
}
26✔
24

25

26
void Var::setValue(const std::vector<unsigned char>& bytes, size_t size, TRICK_TYPE type, bool byteswap) {
64✔
27
    _trick_type = type;
64✔
28
    _var_size = size;
64✔
29
    _byteswap = byteswap;
64✔
30

31
    value_bytes = std::vector<unsigned char> (bytes);
64✔
32
}
64✔
33

34
Number Var::getInterpreter() const {
28✔
35
    Number interpreted_val;
36

37
    if (_byteswap) {
28✔
38
        for (unsigned int i = 0; i < _var_size; i++) {
10✔
39
            interpreted_val.raw_bytes[i] = value_bytes[_var_size - 1 - i];
8✔
40
        }
41
    } else {
42
        for (unsigned int i = 0; i < _var_size; i++) {
135✔
43
            interpreted_val.raw_bytes[i] = value_bytes[i];
109✔
44
        }
45
    }
46

47
    return interpreted_val;
28✔
48
}
49

50
std::string Var::getName() const {
32✔
51
    if (_has_name) {
32✔
52
        return _name;
26✔
53
    } else {
54
        return std::string ("<no name>");
6✔
55
    }
56
}
57

58
TRICK_TYPE Var::getType() const {
22✔
59
    return _trick_type;
22✔
60
}
61

62
std::vector<unsigned char> Var::getRawBytes() const {
2✔
63
    return value_bytes;
2✔
64
}
65

66
int Var::getArraySize() const {
2✔
67
    auto val_size_pair = type_size_map.find(_trick_type);
2✔
68
    if (val_size_pair == type_size_map.end()) {
2✔
69
        return -1;
×
70
    }
71

72
    int val_size = val_size_pair->second;
2✔
73
    if (_var_size % val_size != 0) {
2✔
74
        return -1;
×
75
    }
76

77
    return _var_size / val_size;
2✔
78
}
79

80

81
// Template specialization for each supported type
82
template<>
83
char Var::getValue<char> () const {
2✔
84
    if (_trick_type != TRICK_CHARACTER) {
2✔
85
        throw ParseTypeException();
1✔
86
    }
87

88
    return getInterpreter().char_val;
1✔
89
}
90

91
template<>
92
unsigned char Var::getValue<unsigned char> () const {
2✔
93
    if (_trick_type != TRICK_UNSIGNED_CHARACTER) {
2✔
94
        throw ParseTypeException();
1✔
95
    }
96

97
    return getInterpreter().unsigned_char_val;
1✔
98
}
99

100
template<>
101
bool Var::getValue<bool> () const {
4✔
102
    if (_trick_type != TRICK_BOOLEAN) {
4✔
103
        throw ParseTypeException();
1✔
104
    }
105

106
    return getInterpreter().bool_val;
3✔
107
}
108

109
template<>
110
short Var::getValue<short> () const {
4✔
111
    if (_trick_type != TRICK_SHORT) {
4✔
112
        throw ParseTypeException();
1✔
113
    }
114

115
    return getInterpreter().short_val;
3✔
116
}
117

118
template<>
119
unsigned short Var::getValue<unsigned short> () const {
2✔
120
    if (_trick_type != TRICK_UNSIGNED_SHORT) {
2✔
121
        throw ParseTypeException();
1✔
122
    }
123

124
    return getInterpreter().unsigned_short_val;
1✔
125
}
126

127
template<>
128
unsigned int Var::getValue<unsigned int> () const {
2✔
129
    if (_trick_type != TRICK_UNSIGNED_INTEGER) {
2✔
130
        throw ParseTypeException();
1✔
131
    }
132

133
    return getInterpreter().unsigned_int_val;
1✔
134
}
135

136
template<>
137
int Var::getValue<int> () const {
10✔
138
    if (_trick_type != TRICK_INTEGER) {
10✔
139
        throw ParseTypeException();
1✔
140
    }
141

142
    return getInterpreter().int_val;
9✔
143
}
144

145
template<>
146
long Var::getValue<long> () const {
2✔
147
    if (_trick_type != TRICK_LONG) {
2✔
148
        throw ParseTypeException();
1✔
149
    }
150

151
    return getInterpreter().long_val;
1✔
152
}
153

154
template<>
155
unsigned long Var::getValue<unsigned long> () const {
2✔
156
    if (_trick_type != TRICK_UNSIGNED_LONG) {
2✔
157
        throw ParseTypeException();
1✔
158
    }
159

160
    return getInterpreter().unsigned_long_val;
1✔
161
}
162

163
template<>
164
long long Var::getValue<long long> () const {
4✔
165
    if (_trick_type != TRICK_LONG_LONG) {
4✔
166
        throw ParseTypeException();
1✔
167
    }
168

169
    return getInterpreter().long_long_val;
3✔
170
}
171

172
template<>
173
unsigned long long Var::getValue<unsigned long long> () const {
2✔
174
    if (_trick_type != TRICK_UNSIGNED_LONG_LONG) {
2✔
175
        throw ParseTypeException();
1✔
176
    }
177

178
    return getInterpreter().unsigned_long_long_val;
1✔
179
}
180

181
template<>
182
float Var::getValue<float> () const {
2✔
183
    if (_trick_type != TRICK_FLOAT) {
2✔
184
        throw ParseTypeException();
1✔
185
    }
186

187
    return getInterpreter().float_val;
1✔
188
}
189

190
template<>
191
double Var::getValue<double> () const {
2✔
192
    if (_trick_type != TRICK_DOUBLE) {
2✔
193
        throw ParseTypeException();
1✔
194
    }
195

196
    return getInterpreter().double_val;
1✔
197
}
198

199
template <>
200
std::string Var::getValue<std::string> () const {
11✔
201
    if (_trick_type != TRICK_STRING) {
11✔
202
        throw ParseTypeException();
2✔
203
    }  
204

205
    std::stringstream stream;
18✔
206
    for (unsigned char character : value_bytes) {
698✔
207
        stream << static_cast<char>(character);
689✔
208
    }
209

210
    return stream.str();
18✔
211
}
212

213
template <>
214
wchar_t Var::getValue<wchar_t> () const {
1✔
215
    if (_trick_type != TRICK_WCHAR) {
1✔
216
        throw ParseTypeException();
×
217
    }  
218

219
    return getInterpreter().wchar_val;
1✔
220
}
221

222

223

224
// Utility method
225
uint64_t bytesToInt(const std::vector<unsigned char>& bytes, bool byteswap) {
171✔
226
    uint64_t result = 0;
171✔
227

228
    if (byteswap) {
171✔
229
        for (unsigned int i = 0; i < bytes.size(); i++) {
75✔
230
            result |= bytes[bytes.size() - 1 - i] << i*8;
60✔
231
        }
232
    } else {
233
        for (unsigned int i = 0; i < bytes.size(); i++) {
780✔
234
            result |= bytes[i] << i*8;
624✔
235
        }
236
    }
237

238
    return result;
171✔
239
}
240

241
class MessageIterator {
242
    public:
243
        MessageIterator(const std::vector<unsigned char>& container) : _container(container), _index(0) {}
26✔
244

245
        std::vector<unsigned char> slice(unsigned int length) {
233✔
246
            unsigned int slice_end = _index + length;
233✔
247
            if (_index > _container.size() || slice_end > _container.size()) {
233✔
248
                throw MalformedMessageException("Message ends unexpectedly");
2✔
249
            }
250
            
251
            return std::vector<unsigned char>(_container.begin() + _index, _container.begin() + slice_end);
231✔
252
        }
253

254
        void operator+= (int n) {
229✔
255
            _index += n;
229✔
256
        } 
229✔
257

258
    private:
259
        std::vector<unsigned char> _container;
260
        unsigned int _index; 
261
};
262

263
/**************************************************************************
264
 * Var implementation
265
**************************************************************************/
266

267
const size_t ParsedBinaryMessage::header_size = 12;
268
const size_t ParsedBinaryMessage::message_indicator_size = 4;
269
const size_t ParsedBinaryMessage::variable_num_size = 4;
270
const size_t ParsedBinaryMessage::message_size_size = 4;
271
const size_t ParsedBinaryMessage::variable_name_length_size = 4;
272
const size_t ParsedBinaryMessage::variable_type_size = 4;
273
const size_t ParsedBinaryMessage::variable_size_size = 4;
274

275
// Sometimes, we need to reconstruct the size from the message.
276
// Risk of segfaulting here if the bytes are not correctly formed
277
int ParsedBinaryMessage::parse (char * raw_bytes) {
×
278
    std::vector<unsigned char> bytes;
×
279
    unsigned int i = 0;
×
280
    for ( ; i < message_indicator_size + message_size_size; i++) {
×
281
        bytes.push_back(raw_bytes[i]);
×
282
    }
283

284
    unsigned int message_size = bytesToInt(std::vector<unsigned char> (bytes.begin() + message_indicator_size, bytes.begin() + message_indicator_size + message_size_size), _byteswap);
×
285
    for ( ; i < message_size + message_indicator_size; i++) {
×
286
        bytes.push_back(raw_bytes[i]);
×
287
    }
288

289
    return parse(bytes);
×
290
}
291

292

293
int ParsedBinaryMessage::parse (const std::vector<unsigned char>& bytes) {
27✔
294
    if (bytes.size() < header_size) {
27✔
295
        throw MalformedMessageException(std::string("Not enough bytes in message to contain header: expected at least 12, got " + std::to_string(bytes.size())));
1✔
296
    }
297

298
    MessageIterator messageIterator (bytes);
30✔
299

300
    // First 4 bytes is message type
301
    _message_type = bytesToInt(messageIterator.slice(message_indicator_size), _byteswap);
26✔
302
    if (!validateMessageType(_message_type)) {
26✔
303
        throw MalformedMessageException(std::string("Received unknown message type: " + std::to_string(_message_type)));
1✔
304
    }
305

306
    messageIterator += message_indicator_size;
25✔
307

308
    // Next 4 bytes is message size
309
    _message_size = bytesToInt(messageIterator.slice(message_size_size), _byteswap);
25✔
310
    if (bytes.size() - message_indicator_size != _message_size) {
25✔
311
        std::string error_message = "Message size in header (" + std::to_string(_message_size) + ") does not match size of message received (" + std::to_string(bytes.size() - message_indicator_size) + ")";
3✔
312
        throw MalformedMessageException(error_message);
1✔
313
    }
314

315
    messageIterator += message_size_size;
24✔
316

317
    // Next 4 bytes is number of variables
318
    _num_vars = bytesToInt(messageIterator.slice(variable_num_size), _byteswap);
24✔
319
    messageIterator += variable_num_size;
24✔
320

321
    // Pull out all of the variables
322
    for (unsigned int i = 0; i < _num_vars; i++) {
58✔
323
        Var variable;
72✔
324

325
        if (!_nonames) {
36✔
326
            // Get the name
327
            size_t name_length = bytesToInt(messageIterator.slice(variable_name_length_size), _byteswap);
27✔
328
            messageIterator += variable_name_length_size;
26✔
329

330
            variable.setName(name_length, messageIterator.slice(name_length));
26✔
331
            messageIterator += name_length;
26✔
332
        } 
333

334
        // Parse the type first
335
        int var_type = bytesToInt(messageIterator.slice(variable_type_size), _byteswap);
35✔
336
        messageIterator += variable_type_size;
35✔
337

338
        size_t var_size = bytesToInt(messageIterator.slice(variable_size_size), _byteswap);
35✔
339
        messageIterator += variable_size_size;
35✔
340

341
        variable.setValue(messageIterator.slice(var_size), var_size, static_cast<TRICK_TYPE>(var_type), _byteswap);
35✔
342
        messageIterator += var_size;
34✔
343

344
        variables.emplace_back(variable);
34✔
345
    }
346

347
    return 0;
44✔
348
}
349

350
void ParsedBinaryMessage::combine (const ParsedBinaryMessage& other) {
2✔
351
    if (_message_type != other._message_type) {
2✔
352
        std::string error_message = "Trying to combine two messages with different message indicators (" + std::to_string(_message_type) + " and " + std::to_string(other._message_type) + ")";
3✔
353
        throw MalformedMessageException(error_message);
1✔
354
    }
355

356
    // Combined size - subtract the header size from other message size
357
    _message_size += other._message_size - message_size_size - variable_num_size;
1✔
358
    
359
    // Combine variables
360
    _num_vars += other._num_vars;
1✔
361
    variables.insert(variables.end(), other.variables.begin(), other.variables.end());
1✔
362

363
    // Other error checking - duplicate variables?
364
}
1✔
365

366
Var ParsedBinaryMessage::getVariable(const std::string& name) {
6✔
367
    if (_nonames) 
6✔
368
        throw IncorrectUsageException("Cannot fetch variables by name in noname message");
1✔
369

370
    for (auto variable : variables) {
11✔
371
        if (variable.getName() == name) 
10✔
372
            return variable;
8✔
373
    }
374

375
    throw IncorrectUsageException("Variable " + name + " does not exist in this message.");
1✔
376
}
377

378
Var ParsedBinaryMessage::getVariable(unsigned int index) {
5✔
379
    if (index >= variables.size()) {
5✔
380
        throw IncorrectUsageException("Variable index " + std::to_string(index) + " does not exist in this message.");
1✔
381
    }
382

383
    return variables[index];
4✔
384
}
385

386
int ParsedBinaryMessage::getMessageType() const {
3✔
387
    return _message_type;
3✔
388
}
389

390
unsigned int ParsedBinaryMessage::getMessageSize() const {
1✔
391
    return _message_size;
1✔
392
}
393

394
unsigned int ParsedBinaryMessage::getNumVars() const {
4✔
395
    return _num_vars; 
4✔
396
}
397

398
// Static methods
399

400
bool ParsedBinaryMessage::validateMessageType(int message_type) {
26✔
401
    return message_type >= VS_MIN_CODE && message_type <= VS_MAX_CODE;
26✔
402
}
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