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

dedicate-project / beast / 5908912e-2396-46c2-b03d-62e16fdb292e

pending completion
5908912e-2396-46c2-b03d-62e16fdb292e

Pull #9

circleci

fairlight1337
Added [[nodiscard]] attributes and fixed code smells
Pull Request #9: Adding pipeline applications

1195 of 1195 new or added lines in 21 files covered. (100.0%)

2835 of 3040 relevant lines covered (93.26%)

16628.91 hits per line

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

95.85
/src/vm_session.cpp
1
#include <beast/vm_session.hpp>
2

3
// Standard
4
#include <chrono>
5
#include <ctime>
6
#include <iostream>
7
#include <random>
8
#include <set>
9
#include <stdexcept>
10

11
// Internal
12
#include <beast/time_functions.hpp>
13

14
namespace beast {
15

16
VmSession::VmSession(Program program, size_t variable_count, size_t string_table_count,
5,702✔
17
                     size_t max_string_size)
5,702✔
18
    : program_{std::move(program)}, variable_count_{variable_count},
5,702✔
19
      string_table_count_{string_table_count}, max_string_size_{max_string_size} {
5,702✔
20
  resetRuntimeStatistics();
5,702✔
21
}
5,702✔
22

23
void VmSession::informAboutStep(OpCode operator_code) noexcept {
87,699✔
24
  runtime_statistics_.steps_executed++;
87,699✔
25
  runtime_statistics_.operator_executions[operator_code]++;
87,699✔
26
  runtime_statistics_.executed_indices.insert(pointer_);
87,699✔
27
}
87,699✔
28

29
void VmSession::resetRuntimeStatistics() noexcept { runtime_statistics_ = RuntimeStatistics{}; }
5,708✔
30

31
void VmSession::reset() noexcept {
5✔
32
  resetRuntimeStatistics();
5✔
33
  variables_ = std::map<int32_t, std::pair<VariableDescriptor, int32_t>>{};
5✔
34
  string_table_ = std::map<int32_t, std::string>{};
5✔
35
  print_buffer_ = "";
5✔
36
  pointer_ = 0;
5✔
37
}
5✔
38

39
const VmSession::RuntimeStatistics& VmSession::getRuntimeStatistics() const noexcept {
29✔
40
  return runtime_statistics_;
29✔
41
}
42

43
void VmSession::setVariableBehavior(int32_t variable_index, VariableIoBehavior behavior) {
33,162✔
44
  VariableDescriptor descriptor({Program::VariableType::Int32, behavior, false});
33,162✔
45
  variables_[variable_index] = std::make_pair(descriptor, 0);
33,162✔
46
}
33,162✔
47

48
VmSession::VariableIoBehavior VmSession::getVariableBehavior(int32_t variable_index,
5✔
49
                                                             bool follow_links) {
50
  const auto iterator = variables_.find(getRealVariableIndex(variable_index, follow_links));
5✔
51
  if (iterator == variables_.end()) {
3✔
52
    throw std::invalid_argument("Variable index not declared");
×
53
  }
54
  return iterator->second.first.behavior;
3✔
55
}
56

57
bool VmSession::hasOutputDataAvailable(int32_t variable_index, bool follow_links) {
92,887✔
58
  const auto iterator = variables_.find(getRealVariableIndex(variable_index, follow_links));
92,887✔
59
  if (iterator == variables_.end()) {
92,879✔
60
    throw std::invalid_argument("Variable index not declared");
×
61
  }
62
  if (iterator->second.first.behavior != VariableIoBehavior::Output) {
92,879✔
63
    throw std::invalid_argument("Variable behavior not declared as output");
2✔
64
  }
65
  return iterator->second.first.changed_since_last_interaction;
92,877✔
66
}
67

68
void VmSession::setMaximumPrintBufferLength(size_t maximum_print_buffer_length) {
1✔
69
  maximum_print_buffer_length_ = maximum_print_buffer_length;
1✔
70
}
1✔
71

72
int32_t VmSession::getData4() {
136,463✔
73
  int32_t data = program_.getData4(pointer_);
136,463✔
74
  pointer_ += 4;
136,456✔
75
  return data;
136,456✔
76
}
77

78
int16_t VmSession::getData2() {
123✔
79
  int16_t data = program_.getData2(pointer_);
123✔
80
  pointer_ += 2;
123✔
81
  return data;
123✔
82
}
83

84
int8_t VmSession::getData1() {
214,319✔
85
  int8_t data = program_.getData1(pointer_);
214,319✔
86
  pointer_ += 1;
214,313✔
87
  return data;
214,313✔
88
}
89

90
int32_t VmSession::getVariableValue(int32_t variable_index, bool follow_links) {
7,775✔
91
  auto& [variable, value] = variables_[getRealVariableIndex(variable_index, follow_links)];
7,775✔
92
  if (variable.behavior == VariableIoBehavior::Output) {
7,775✔
93
    variable.changed_since_last_interaction = false;
7,670✔
94
  }
95
  return value;
7,775✔
96
}
97

98
int32_t VmSession::getVariableValueInternal(int32_t variable_index, bool follow_links) {
107,846✔
99
  auto& [variable, value] = variables_[getRealVariableIndex(variable_index, follow_links)];
107,846✔
100
  if (variable.behavior == VariableIoBehavior::Input) {
106,307✔
101
    variable.changed_since_last_interaction = false;
13,038✔
102
  }
103
  return value;
106,307✔
104
}
105

106
void VmSession::setVariableValue(int32_t variable_index, bool follow_links, int32_t value) {
16,572✔
107
  auto& [variable, current_value] = variables_[getRealVariableIndex(variable_index, follow_links)];
16,572✔
108
  if (variable.behavior == VariableIoBehavior::Input) {
16,572✔
109
    variable.changed_since_last_interaction = true;
16,572✔
110
  }
111
  current_value = value;
16,572✔
112
}
16,572✔
113

114
void VmSession::setVariableValueInternal(int32_t variable_index, bool follow_links, int32_t value) {
14,551✔
115
  auto& [variable, current_value] = variables_[getRealVariableIndex(variable_index, follow_links)];
14,551✔
116
  if (variable.behavior == VariableIoBehavior::Output) {
14,022✔
117
    variable.changed_since_last_interaction = true;
7,712✔
118
  }
119
  current_value = value;
14,022✔
120
}
14,022✔
121

122
bool VmSession::isAtEnd() const noexcept {
84,794✔
123
  return runtime_statistics_.terminated || pointer_ >= program_.getSize();
84,794✔
124
}
125

126
void VmSession::setExitedAbnormally() { runtime_statistics_.abnormal_exit = true; }
3✔
127

128
void VmSession::registerVariable(int32_t variable_index, Program::VariableType variable_type) {
509✔
129
  if (variable_index < 0 || variable_index >= variable_count_) {
509✔
130
    throw std::out_of_range("Invalid variable index.");
2✔
131
  }
132

133
  if (variable_type != Program::VariableType::Int32 &&
507✔
134
      variable_type != Program::VariableType::Link) {
135
    throw std::invalid_argument("Invalid declarative variable type.");
×
136
  }
137

138
  if (variables_.find(variable_index) != variables_.end()) {
507✔
139
    throw std::invalid_argument("Variable index already declared.");
23✔
140
  }
141

142
  if (variables_.size() == variable_count_) {
484✔
143
    // No more space for variables
144
    throw std::overflow_error("Variables cache full.");
×
145
  }
146

147
  VariableDescriptor descriptor({variable_type, VariableIoBehavior::Store, false});
484✔
148
  variables_[variable_index] = std::make_pair(descriptor, 0);
484✔
149
}
484✔
150

151
int32_t VmSession::getRealVariableIndex(int32_t variable_index, bool follow_links) {
240,416✔
152
  std::set<int32_t> visited_indices;
242,565✔
153
  std::map<int32_t, std::pair<VariableDescriptor, int32_t>>::iterator iterator;
240,416✔
154

155
  while ((iterator = variables_.find(variable_index)) != variables_.end()) {
240,728✔
156
    if (iterator->second.first.type != Program::VariableType::Link || !follow_links) {
238,579✔
157
      // This is a non-link variable, return it.
158
      return variable_index;
476,534✔
159
    }
160

161
    if (iterator->second.first.type == Program::VariableType::Link) {
312✔
162
      if (visited_indices.find(variable_index) != visited_indices.end()) {
312✔
163
        throw std::invalid_argument("Circular variable index link.");
×
164
      }
165
      visited_indices.insert(variable_index);
312✔
166
      variable_index = getVariableValueInternal(variable_index, false);
312✔
167
    } else {
168
      throw std::invalid_argument("Invalid declarative variable type.");
×
169
    }
170
  }
171

172
  // Undeclared variables cannot be set.
173
  throw std::invalid_argument("Variable index not declared.");
2,149✔
174
}
175

176
void VmSession::setVariable(int32_t variable_index, int32_t value, bool follow_links) {
3,183✔
177
  setVariableValueInternal(variable_index, follow_links, value);
3,183✔
178
}
3,136✔
179

180
void VmSession::unregisterVariable(int32_t variable_index) {
82✔
181
  if (variable_index < 0 || variable_index >= variable_count_) {
82✔
182
    throw std::out_of_range("Invalid variable index.");
×
183
  }
184

185
  if (variables_.find(variable_index) == variables_.end()) {
82✔
186
    throw std::invalid_argument("Variable index not declared, cannot undeclare.");
57✔
187
  }
188

189
  variables_.erase(variable_index);
25✔
190
}
25✔
191

192
void VmSession::setStringTableEntry(int32_t string_table_index, std::string_view string_content) {
89✔
193
  if (string_table_index < 0 || string_table_index >= string_table_count_) {
89✔
194
    throw std::out_of_range("String table index out of bounds.");
73✔
195
  }
196

197
  if (string_content.size() > max_string_size_) {
16✔
198
    throw std::length_error("String too long.");
×
199
  }
200

201
  string_table_[string_table_index] = string_content;
16✔
202
}
16✔
203

204
const std::string& VmSession::getStringTableEntry(int32_t string_table_index) const {
79✔
205
  const auto iterator = string_table_.find(string_table_index);
79✔
206
  if (iterator == string_table_.end()) {
79✔
207
    throw std::out_of_range("String table index out of bounds.");
69✔
208
  }
209

210
  return iterator->second;
10✔
211
}
212

213
void VmSession::appendToPrintBuffer(std::string_view string) {
221✔
214
  if (print_buffer_.size() + string.size() > maximum_print_buffer_length_) {
221✔
215
    throw std::overflow_error("Print buffer overflow.");
1✔
216
  }
217
  print_buffer_ += string;
220✔
218
}
220✔
219

220
void VmSession::appendVariableToPrintBuffer(int32_t variable_index, bool follow_links,
216✔
221
                                            bool as_char) {
222
  variable_index = getRealVariableIndex(variable_index, follow_links);
216✔
223
  if (variables_[variable_index].first.type == Program::VariableType::Int32) {
210✔
224
    if (as_char) {
210✔
225
      const uint32_t flag = 0xff;
25✔
226
      const auto val = static_cast<char>(
227
          static_cast<uint32_t>(getVariableValueInternal(variable_index, false)) & flag);
25✔
228
      appendToPrintBuffer(std::string_view(&val, 1));
25✔
229
    } else {
230
      appendToPrintBuffer(std::to_string(getVariableValueInternal(variable_index, false)));
185✔
231
    }
232
  } else if (variables_[variable_index].first.type == Program::VariableType::Link) {
×
233
    appendToPrintBuffer("L{" + std::to_string(getVariableValueInternal(variable_index, false)) +
×
234
                        "}");
235
  } else {
236
    throw std::invalid_argument(
237
        "Cannot print unsupported variable type (" +
×
238
        std::to_string(static_cast<int32_t>(variables_[variable_index].first.type)) + ").");
×
239
  }
240
}
210✔
241

242
const std::string& VmSession::getPrintBuffer() const { return print_buffer_; }
11✔
243

244
void VmSession::clearPrintBuffer() { print_buffer_ = ""; }
1✔
245

246
void VmSession::terminate(int8_t return_code) {
710✔
247
  runtime_statistics_.return_code = return_code;
710✔
248
  runtime_statistics_.terminated = true;
710✔
249
}
710✔
250

251
void VmSession::addConstantToVariable(int32_t variable_index, int32_t constant, bool follow_links) {
843✔
252
  setVariableValueInternal(variable_index,
762✔
253
                           follow_links,
254
                           getVariableValueInternal(variable_index, follow_links) + constant);
843✔
255
}
762✔
256

257
void VmSession::addVariableToVariable(int32_t source_variable, int32_t destination_variable,
140✔
258
                                      bool follow_source_links, bool follow_destination_links) {
259
  setVariableValueInternal(
126✔
260
      destination_variable,
261
      follow_destination_links,
262
      getVariableValueInternal(destination_variable, follow_destination_links) +
140✔
263
          getVariableValueInternal(source_variable, follow_source_links));
129✔
264
}
126✔
265

266
void VmSession::subtractConstantFromVariable(int32_t variable_index, int32_t constant,
378✔
267
                                             bool follow_links) {
268
  setVariableValueInternal(variable_index,
372✔
269
                           follow_links,
270
                           getVariableValueInternal(variable_index, follow_links) - constant);
378✔
271
}
372✔
272

273
void VmSession::subtractVariableFromVariable(int32_t source_variable, int32_t destination_variable,
32✔
274
                                             bool follow_source_links,
275
                                             bool follow_destination_links) {
276
  setVariableValueInternal(
9✔
277
      destination_variable,
278
      follow_destination_links,
279
      getVariableValueInternal(destination_variable, follow_destination_links) -
32✔
280
          getVariableValueInternal(source_variable, follow_source_links));
9✔
281
}
9✔
282

283
void VmSession::relativeJumpToVariableAddressIfVariableGt0(int32_t condition_variable,
819✔
284
                                                           bool follow_condition_links,
285
                                                           int32_t addr_variable,
286
                                                           bool follow_addr_links) {
287
  if (getVariableValueInternal(condition_variable, follow_condition_links) > 0) {
819✔
288
    pointer_ += getVariableValueInternal(addr_variable, follow_addr_links);
43✔
289
  }
290
}
803✔
291

292
void VmSession::relativeJumpToVariableAddressIfVariableLt0(int32_t condition_variable,
46✔
293
                                                           bool follow_condition_links,
294
                                                           int32_t addr_variable,
295
                                                           bool follow_addr_links) {
296
  if (getVariableValueInternal(condition_variable, follow_condition_links) < 0) {
46✔
297
    pointer_ += getVariableValueInternal(addr_variable, follow_addr_links);
1✔
298
  }
299
}
25✔
300

301
void VmSession::relativeJumpToVariableAddressIfVariableEq0(int32_t condition_variable,
100✔
302
                                                           bool follow_condition_links,
303
                                                           int32_t addr_variable,
304
                                                           bool follow_addr_links) {
305
  if (getVariableValueInternal(condition_variable, follow_condition_links) == 0) {
100✔
306
    pointer_ += getVariableValueInternal(addr_variable, follow_addr_links);
78✔
307
  }
308
}
85✔
309

310
void VmSession::absoluteJumpToVariableAddressIfVariableGt0(int32_t condition_variable,
5,456✔
311
                                                           bool follow_condition_links,
312
                                                           int32_t addr_variable,
313
                                                           bool follow_addr_links) {
314
  if (getVariableValueInternal(condition_variable, follow_condition_links) > 0) {
5,456✔
315
    pointer_ = getVariableValueInternal(addr_variable, follow_addr_links);
345✔
316
  }
317
}
5,412✔
318

319
void VmSession::absoluteJumpToVariableAddressIfVariableLt0(int32_t condition_variable,
80✔
320
                                                           bool follow_condition_links,
321
                                                           int32_t addr_variable,
322
                                                           bool follow_addr_links) {
323
  if (getVariableValueInternal(condition_variable, follow_condition_links) < 0) {
80✔
324
    pointer_ = getVariableValueInternal(addr_variable, follow_addr_links);
4✔
325
  }
326
}
53✔
327

328
void VmSession::absoluteJumpToVariableAddressIfVariableEq0(int32_t condition_variable,
31,023✔
329
                                                           bool follow_condition_links,
330
                                                           int32_t addr_variable,
331
                                                           bool follow_addr_links) {
332
  if (getVariableValueInternal(condition_variable, follow_condition_links) == 0) {
31,023✔
333
    pointer_ = getVariableValueInternal(addr_variable, follow_addr_links);
30,938✔
334
  }
335
}
30,950✔
336

337
void VmSession::relativeJumpToAddressIfVariableGt0(int32_t condition_variable,
645✔
338
                                                   bool follow_condition_links, int32_t addr) {
339
  if (getVariableValueInternal(condition_variable, follow_condition_links) > 0) {
645✔
340
    pointer_ += addr;
163✔
341
  }
342
}
616✔
343

344
void VmSession::relativeJumpToAddressIfVariableLt0(int32_t condition_variable,
192✔
345
                                                   bool follow_condition_links, int32_t addr) {
346
  if (getVariableValueInternal(condition_variable, follow_condition_links) < 0) {
192✔
347
    pointer_ += addr;
11✔
348
  }
349
}
177✔
350

351
void VmSession::relativeJumpToAddressIfVariableEq0(int32_t condition_variable,
1,406✔
352
                                                   bool follow_condition_links, int32_t addr) {
353
  if (getVariableValueInternal(condition_variable, follow_condition_links) == 0) {
1,406✔
354
    pointer_ += addr;
1,310✔
355
  }
356
}
1,369✔
357

358
void VmSession::absoluteJumpToAddressIfVariableGt0(int32_t condition_variable,
211✔
359
                                                   bool follow_condition_links, int32_t addr) {
360
  if (getVariableValueInternal(condition_variable, follow_condition_links) > 0) {
211✔
361
    pointer_ = addr;
135✔
362
  }
363
}
193✔
364

365
void VmSession::absoluteJumpToAddressIfVariableLt0(int32_t condition_variable,
41✔
366
                                                   bool follow_condition_links, int32_t addr) {
367
  if (getVariableValueInternal(condition_variable, follow_condition_links) < 0) {
41✔
368
    pointer_ = addr;
3✔
369
  }
370
}
13✔
371

372
void VmSession::absoluteJumpToAddressIfVariableEq0(int32_t condition_variable,
810✔
373
                                                   bool follow_condition_links, int32_t addr) {
374
  if (getVariableValueInternal(condition_variable, follow_condition_links) == 0) {
810✔
375
    pointer_ = addr;
766✔
376
  }
377
}
783✔
378

379
void VmSession::loadMemorySizeIntoVariable(int32_t variable, bool follow_links) {
598✔
380
  setVariableValueInternal(variable, follow_links, static_cast<int32_t>(variable_count_));
598✔
381
}
461✔
382

383
void VmSession::checkIfVariableIsInput(int32_t source_variable, bool follow_source_links,
221✔
384
                                       int32_t destination_variable,
385
                                       bool follow_destination_links) {
386
  setVariableValueInternal(
181✔
387
      destination_variable,
388
      follow_destination_links,
389
      variables_[getRealVariableIndex(source_variable, follow_source_links)].first.behavior ==
221✔
390
              VmSession::VariableIoBehavior::Input
391
          ? 0x1
392
          : 0x0);
393
}
174✔
394

395
void VmSession::checkIfVariableIsOutput(int32_t source_variable, bool follow_source_links,
62✔
396
                                        int32_t destination_variable,
397
                                        bool follow_destination_links) {
398
  setVariableValueInternal(
57✔
399
      destination_variable,
400
      follow_destination_links,
401
      variables_[getRealVariableIndex(source_variable, follow_source_links)].first.behavior ==
62✔
402
              VmSession::VariableIoBehavior::Output
403
          ? 0x1
404
          : 0x0);
405
}
54✔
406

407
void VmSession::copyVariable(int32_t source_variable, bool follow_source_links,
408✔
408
                             int32_t destination_variable, bool follow_destination_links) {
409
  setVariableValueInternal(destination_variable,
408✔
410
                           follow_destination_links,
411
                           getVariableValueInternal(source_variable, follow_source_links));
412
}
384✔
413

414
void VmSession::loadInputCountIntoVariable(int32_t variable, bool follow_links) {
222✔
415
  int32_t input_count = 0;
222✔
416
  for (const auto& [index, variable_data] : variables_) {
670✔
417
    if (variable_data.first.behavior == VariableIoBehavior::Input) {
448✔
418
      input_count++;
223✔
419
    }
420
  }
421
  setVariableValueInternal(variable, follow_links, input_count);
222✔
422
}
189✔
423

424
void VmSession::loadOutputCountIntoVariable(int32_t variable, bool follow_links) {
334✔
425
  int32_t output_count = 0;
334✔
426
  for (const auto& [index, variable_data] : variables_) {
1,006✔
427
    if (variable_data.first.behavior == VariableIoBehavior::Output) {
672✔
428
      output_count++;
336✔
429
    }
430
  }
431
  setVariableValueInternal(variable, follow_links, output_count);
334✔
432
}
329✔
433

434
void VmSession::loadCurrentAddressIntoVariable(int32_t variable, bool follow_links) {
118✔
435
  setVariableValueInternal(variable, follow_links, pointer_);
118✔
436
}
41✔
437

438
void VmSession::checkIfInputWasSet(int32_t variable_index, bool follow_links,
281✔
439
                                   int32_t destination_variable, bool follow_destination_links) {
440
  auto& [variable, value] = variables_[getRealVariableIndex(variable_index, follow_links)];
281✔
441
  if (variable.behavior != VariableIoBehavior::Input) {
261✔
442
    throw std::invalid_argument("Variable is not an input.");
26✔
443
  }
444

445
  setVariableValueInternal(destination_variable,
235✔
446
                           follow_destination_links,
447
                           variable.changed_since_last_interaction ? 0x1 : 0x0);
235✔
448
  variable.changed_since_last_interaction = false;
231✔
449
}
231✔
450

451
void VmSession::loadStringTableLimitIntoVariable(int32_t variable_index, bool follow_links) {
157✔
452
  setVariableValueInternal(variable_index, follow_links, static_cast<int32_t>(string_table_count_));
157✔
453
}
149✔
454

455
void VmSession::loadStringTableItemLengthLimitIntoVariable(int32_t variable_index,
228✔
456
                                                           bool follow_links) {
457
  setVariableValueInternal(variable_index, follow_links, static_cast<int32_t>(max_string_size_));
228✔
458
}
194✔
459

460
void VmSession::loadRandomValueIntoVariable(int32_t variable_index, bool follow_links) {
450✔
461
  // NOTE(fairlight1337): The initialization of the `rng` variable is not linted
462
  // here to prevent clang-tidy from complaining about seeding with a value from
463
  // the default constructor. Since we're using `random_device` to seed `rng`
464
  // right after, this warning is discarded explicitly. NOLINTNEXTLINE
465
  std::mt19937 rng;
450✔
466
  std::random_device random_device;
900✔
467
  rng.seed(random_device());
450✔
468
  std::uniform_int_distribution<int32_t> distribution;
450✔
469
  setVariableValueInternal(variable_index, follow_links, distribution(rng));
450✔
470
}
428✔
471

472
void VmSession::unconditionalJumpToAbsoluteAddress(int32_t addr) { pointer_ = addr; }
532✔
473

474
void VmSession::unconditionalJumpToAbsoluteVariableAddress(int32_t variable_index,
20,617✔
475
                                                           bool follow_links) {
476
  pointer_ = getVariableValueInternal(variable_index, follow_links);
20,617✔
477
}
20,581✔
478

479
void VmSession::unconditionalJumpToRelativeAddress(int32_t addr) { pointer_ += addr; }
1,428✔
480

481
void VmSession::unconditionalJumpToRelativeVariableAddress(int32_t variable_index,
502✔
482
                                                           bool follow_links) {
483
  pointer_ += getVariableValueInternal(variable_index, follow_links);
502✔
484
}
436✔
485

486
void VmSession::loadStringItemLengthIntoVariable(int32_t string_table_index, int32_t variable_index,
53✔
487
                                                 bool follow_links) {
488
  if (string_table_index < 0 || string_table_index >= string_table_count_) {
53✔
489
    throw std::out_of_range("String table index out of bounds.");
51✔
490
  }
491

492
  setVariableValueInternal(
2✔
493
      variable_index, follow_links, static_cast<int32_t>(string_table_[string_table_index].size()));
2✔
494
}
2✔
495

496
void VmSession::loadStringItemIntoVariables(int32_t string_table_index,
40✔
497
                                            int32_t start_variable_index, bool follow_links) {
498
  if (string_table_index < 0 || string_table_index >= string_table_count_) {
40✔
499
    throw std::out_of_range("String table index out of bounds.");
38✔
500
  }
501

502
  const auto iterator = string_table_.find(string_table_index);
2✔
503
  if (iterator == string_table_.end()) {
2✔
504
    throw std::invalid_argument("String table index not defined.");
×
505
  }
506

507
  const size_t size = iterator->second.size();
2✔
508
  for (uint32_t idx = 0; idx < size; ++idx) {
12✔
509
    setVariableValueInternal(start_variable_index + static_cast<int32_t>(idx),
10✔
510
                             follow_links,
511
                             static_cast<int32_t>(iterator->second.at(idx)));
10✔
512
  }
513
}
2✔
514

515
void VmSession::performSystemCall(int8_t major_code, int8_t minor_code, int32_t variable_index,
57✔
516
                                  bool follow_links) {
517
  if (major_code == 0) { // Time and date related functions
57✔
518
    // Get the current UTC time
519
    const auto now_utc = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
9✔
520
    std::tm utc_tm{};
9✔
521
    if (gmtime_r(&now_utc, &utc_tm) == nullptr) {
9✔
522
      throw std::domain_error("Time conversion failed.");
×
523
    }
524

525
    // Get the current local time
526
    const auto now_local = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
9✔
527
    std::tm local_tm{};
9✔
528
    if (localtime_r(&now_local, &local_tm) == nullptr) {
9✔
529
      throw std::domain_error("Time conversion failed.");
×
530
    }
531

532
    const int32_t offset_minutes =
9✔
533
        (local_tm.tm_hour - utc_tm.tm_hour) * 60 + (local_tm.tm_min - utc_tm.tm_min);
9✔
534

535
    switch (minor_code) {
9✔
536
    case 0: { // UTC Timezone (hours)
1✔
537
      // Calculate the timezone offset in minutes
538
      const auto utc_offset_hours =
1✔
539
          static_cast<int32_t>(std::floor(static_cast<double>(offset_minutes) / 60.0));
1✔
540
      setVariableValueInternal(variable_index, follow_links, utc_offset_hours);
1✔
541
    } break;
1✔
542

543
    case 1: { // UTC Timezone (minutes)
1✔
544
      // Calculate the timezone offset in minutes
545
      const int32_t utc_offset_minutes = offset_minutes % 60;
1✔
546
      setVariableValueInternal(variable_index, follow_links, utc_offset_minutes);
1✔
547
    } break;
1✔
548

549
    case 2: { // Seconds
1✔
550
      setVariableValueInternal(variable_index, follow_links, utc_tm.tm_sec);
1✔
551
    } break;
1✔
552

553
    case 3: { // Minutes
1✔
554
      setVariableValueInternal(variable_index, follow_links, utc_tm.tm_min);
1✔
555
    } break;
1✔
556

557
    case 4: { // Hours
1✔
558
      setVariableValueInternal(variable_index, follow_links, utc_tm.tm_hour);
1✔
559
    } break;
1✔
560

561
    case 5: { // Day
1✔
562
      setVariableValueInternal(variable_index, follow_links, utc_tm.tm_mday);
1✔
563
    } break;
1✔
564

565
    case 6: { // Month
1✔
566
      setVariableValueInternal(variable_index, follow_links, utc_tm.tm_mon);
1✔
567
    } break;
1✔
568

569
    case 7: { // Year
1✔
570
      setVariableValueInternal(variable_index, follow_links, utc_tm.tm_year);
1✔
571
    } break;
1✔
572

573
    case 8: { // Week
1✔
574
      const int32_t current_year = utc_tm.tm_year + 1900;
1✔
575
      const int32_t current_day = utc_tm.tm_mday;
1✔
576

577
      // Calculate the first day of the current year
578
      std::tm first_day_of_year{};
1✔
579
      first_day_of_year.tm_year = current_year - 1900;
1✔
580
      first_day_of_year.tm_mon = 0; // January
1✔
581
      first_day_of_year.tm_mday = 1;
1✔
582

583
      const std::time_t first_day_time = std::mktime(&first_day_of_year);
1✔
584
      std::tm first_day_tm{};
1✔
585
      if (gmtime_r(&first_day_time, &first_day_tm) == nullptr) {
1✔
586
        throw std::domain_error("Time conversion failed.");
×
587
      }
588

589
      const int32_t first_day_weekday = first_day_tm.tm_wday;
1✔
590

591
      const int32_t current_week = (current_day - 1 + first_day_weekday) / 7 + 1;
1✔
592
      setVariableValueInternal(variable_index, follow_links, current_week);
1✔
593
    } break;
1✔
594

595
    case 9: { // Day of Week
×
596
      setVariableValueInternal(variable_index, follow_links, utc_tm.tm_wday);
×
597
    } break;
×
598

599
    default:
×
600
      throw std::invalid_argument("Unknown major/minor code combination for system call: " +
×
601
                                  std::to_string(major_code) + ", " + std::to_string(minor_code));
×
602
    }
603
  } else {
604
    throw std::invalid_argument("Unknown major code for system call: " +
96✔
605
                                std::to_string(major_code));
144✔
606
  }
607
}
9✔
608

609
void VmSession::bitShiftVariable(int32_t variable_index, bool follow_links, int8_t places) {
700✔
610
  const auto value = static_cast<uint32_t>(getVariableValueInternal(variable_index, follow_links));
700✔
611
  const auto shifted_value =
657✔
612
      places > 0 ? value << static_cast<uint32_t>(places) : value >> static_cast<uint32_t>(-places);
657✔
613
  setVariableValueInternal(variable_index, follow_links, static_cast<int32_t>(shifted_value));
657✔
614
}
657✔
615

616
void VmSession::bitWiseInvertVariable(int32_t variable_index, bool follow_links) {
178✔
617
  const auto value = static_cast<uint32_t>(getVariableValueInternal(variable_index, follow_links));
178✔
618
  const auto inverted_value = ~value;
155✔
619
  setVariableValueInternal(variable_index, follow_links, static_cast<int32_t>(inverted_value));
155✔
620
}
155✔
621

622
void VmSession::bitWiseAndTwoVariables(int32_t variable_index_a, bool follow_links_a,
148✔
623
                                       int32_t variable_index_b, bool follow_links_b) {
624
  const auto value_a =
625
      static_cast<uint32_t>(getVariableValueInternal(variable_index_a, follow_links_a));
148✔
626
  const auto value_b =
627
      static_cast<uint32_t>(getVariableValueInternal(variable_index_b, follow_links_b));
137✔
628
  const uint32_t result = value_a & value_b;
132✔
629
  setVariableValueInternal(variable_index_b, follow_links_b, static_cast<int32_t>(result));
132✔
630
}
132✔
631

632
void VmSession::bitWiseOrTwoVariables(int32_t variable_index_a, bool follow_links_a,
415✔
633
                                      int32_t variable_index_b, bool follow_links_b) {
634
  const auto value_a =
635
      static_cast<uint32_t>(getVariableValueInternal(variable_index_a, follow_links_a));
415✔
636
  const auto value_b =
637
      static_cast<uint32_t>(getVariableValueInternal(variable_index_b, follow_links_b));
412✔
638
  const uint32_t result = value_a | value_b;
399✔
639
  setVariableValueInternal(variable_index_b, follow_links_b, static_cast<int32_t>(result));
399✔
640
}
399✔
641

642
void VmSession::bitWiseXorTwoVariables(int32_t variable_index_a, bool follow_links_a,
219✔
643
                                       int32_t variable_index_b, bool follow_links_b) {
644
  const auto value_a =
645
      static_cast<uint32_t>(getVariableValueInternal(variable_index_a, follow_links_a));
219✔
646
  const auto value_b =
647
      static_cast<uint32_t>(getVariableValueInternal(variable_index_b, follow_links_b));
202✔
648
  const uint32_t result = value_a ^ value_b;
195✔
649
  setVariableValueInternal(variable_index_b, follow_links_b, static_cast<int32_t>(result));
195✔
650
}
195✔
651

652
void VmSession::moduloVariableByConstant(int32_t variable_index, bool follow_links,
68✔
653
                                         int32_t constant) {
654
  if (constant <= 0) {
68✔
655
    throw std::invalid_argument("Cannot modulo with a constant <= 0.");
23✔
656
  }
657

658
  const int32_t value = getVariableValueInternal(variable_index, follow_links);
45✔
659
  const int32_t result = value % constant;
26✔
660
  setVariableValueInternal(variable_index, follow_links, result);
26✔
661
}
26✔
662

663
void VmSession::moduloVariableByVariable(int32_t variable_index, bool follow_links,
64✔
664
                                         int32_t modulo_variable_index, bool modulo_follow_links) {
665
  const int32_t value = getVariableValueInternal(variable_index, follow_links);
64✔
666
  const int32_t modulo_value = getVariableValueInternal(modulo_variable_index, modulo_follow_links);
46✔
667
  if (modulo_value <= 0) {
39✔
668
    throw std::invalid_argument("Cannot modulo with a modulo value <= 0.");
23✔
669
  }
670

671
  const int32_t result = value % modulo_value;
16✔
672
  setVariableValueInternal(variable_index, follow_links, result);
16✔
673
}
16✔
674

675
void VmSession::rotateVariable(int32_t variable_index, bool follow_links, int8_t places) {
948✔
676
  const auto value = static_cast<uint32_t>(getVariableValueInternal(variable_index, follow_links));
948✔
677
  const auto abs_places = static_cast<uint8_t>(std::abs(places));
895✔
678
  if (places < 0) {
895✔
679
    // Rotate right
680
    const uint32_t result =
403✔
681
        (value >> abs_places) | (value << static_cast<uint32_t>(32 - abs_places));
403✔
682
    setVariableValueInternal(variable_index, follow_links, static_cast<int32_t>(result));
403✔
683
  } else {
684
    // Rotate left
685
    const uint32_t result =
492✔
686
        (value << abs_places) | (value >> static_cast<uint32_t>(32 - abs_places));
492✔
687
    setVariableValueInternal(variable_index, follow_links, static_cast<int32_t>(result));
492✔
688
  }
689
}
895✔
690

691
void VmSession::pushVariableOnStack(int32_t stack_variable_index, bool stack_follow_links,
71✔
692
                                    int32_t variable_index, bool follow_links) {
693
  const int32_t current_stack_size =
694
      getVariableValueInternal(stack_variable_index, stack_follow_links);
71✔
695
  const int32_t new_value = getVariableValueInternal(variable_index, follow_links);
35✔
696
  setVariableValueInternal(
8✔
697
      stack_variable_index + 1 + current_stack_size, stack_follow_links, new_value);
8✔
698
  setVariableValueInternal(stack_variable_index, stack_follow_links, current_stack_size + 1);
3✔
699
}
3✔
700

701
void VmSession::pushConstantOnStack(int32_t stack_variable_index, bool stack_follow_links,
264✔
702
                                    int32_t constant) {
703
  const int32_t current_stack_size =
704
      getVariableValueInternal(stack_variable_index, stack_follow_links);
264✔
705
  setVariableValueInternal(
247✔
706
      stack_variable_index + 1 + current_stack_size, stack_follow_links, constant);
247✔
707
  setVariableValueInternal(stack_variable_index, stack_follow_links, current_stack_size + 1);
234✔
708
}
234✔
709

710
void VmSession::popVariableFromStack(int32_t stack_variable_index, bool stack_follow_links,
121✔
711
                                     int32_t variable_index, bool follow_links) {
712
  const int32_t current_stack_size =
713
      getVariableValueInternal(stack_variable_index, stack_follow_links);
121✔
714
  if (current_stack_size == 0) {
71✔
715
    throw std::underflow_error("Cannot pop value from stack, stack empty.");
18✔
716
  }
717
  const int32_t last_value = getVariableValueInternal(
89✔
718
      stack_variable_index + 1 + current_stack_size - 1, stack_follow_links);
53✔
719
  setVariableValueInternal(stack_variable_index, true, current_stack_size - 1);
36✔
720
  setVariableValueInternal(variable_index, follow_links, last_value);
36✔
721
}
36✔
722

723
void VmSession::popTopItemFromStack(int32_t stack_variable_index, bool stack_follow_links) {
148✔
724
  const int32_t current_stack_size =
725
      getVariableValueInternal(stack_variable_index, stack_follow_links);
148✔
726
  if (current_stack_size == 0) {
109✔
727
    throw std::underflow_error("Cannot pop value from stack, stack empty.");
7✔
728
  }
729
  setVariableValueInternal(stack_variable_index, true, current_stack_size - 1);
102✔
730
}
102✔
731

732
void VmSession::checkIfStackIsEmpty(int32_t stack_variable_index, bool stack_follow_links,
348✔
733
                                    int32_t variable_index, bool follow_links) {
734
  const int32_t value = getVariableValueInternal(stack_variable_index, stack_follow_links);
348✔
735
  setVariableValueInternal(variable_index, follow_links, value == 0x0 ? 0x1 : 0x0);
317✔
736
}
297✔
737

738
void VmSession::swapVariables(int32_t variable_index_a, bool follow_links_a,
738✔
739
                              int32_t variable_index_b, bool follow_links_b) {
740
  const int32_t temp = getVariableValueInternal(variable_index_a, follow_links_a);
738✔
741
  setVariableValueInternal(
732✔
742
      variable_index_a, follow_links_a, getVariableValueInternal(variable_index_b, follow_links_b));
743
  setVariableValueInternal(variable_index_b, follow_links_b, temp);
721✔
744
}
721✔
745

746
void VmSession::setVariableStringTableEntry(int32_t variable_index, bool follow_links,
32✔
747
                                            std::string_view string_content) {
748
  const int32_t string_table_index = getVariableValueInternal(variable_index, follow_links);
32✔
749
  if (string_table_index < 0 || string_table_index >= string_table_count_) {
19✔
750
    throw std::out_of_range("String table index out of bounds.");
17✔
751
  }
752

753
  if (string_content.size() > max_string_size_) {
2✔
754
    throw std::length_error("String too long.");
1✔
755
  }
756

757
  string_table_[string_table_index] = string_content;
1✔
758
}
1✔
759

760
void VmSession::printVariableStringFromStringTable(int32_t variable_index, bool follow_links) {
98✔
761
  const int32_t string_table_index = getVariableValueInternal(variable_index, follow_links);
98✔
762
  if (string_table_index < 0 || string_table_index >= string_table_count_) {
93✔
763
    throw std::out_of_range("String table index out of bounds.");
92✔
764
  }
765

766
  appendToPrintBuffer(getStringTableEntry(string_table_index));
1✔
767
}
1✔
768

769
void VmSession::loadVariableStringItemLengthIntoVariable(int32_t string_item_variable_index,
41✔
770
                                                         bool string_item_follow_links,
771
                                                         int32_t variable_index,
772
                                                         bool follow_links) {
773
  const int32_t string_table_index =
774
      getVariableValueInternal(string_item_variable_index, string_item_follow_links);
41✔
775
  if (string_table_index < 0 || string_table_index >= string_table_count_) {
28✔
776
    throw std::out_of_range("String table index out of bounds.");
26✔
777
  }
778

779
  setVariableValueInternal(
2✔
780
      variable_index, follow_links, static_cast<int32_t>(string_table_[string_table_index].size()));
2✔
781
}
2✔
782

783
void VmSession::loadVariableStringItemIntoVariables(int32_t string_item_variable_index,
119✔
784
                                                    bool string_item_follow_links,
785
                                                    int32_t start_variable_index,
786
                                                    bool follow_links) {
787
  const int32_t string_table_index =
788
      getVariableValueInternal(string_item_variable_index, string_item_follow_links);
119✔
789
  if (string_table_index < 0 || string_table_index >= string_table_count_) {
80✔
790
    throw std::out_of_range("String table index out of bounds.");
79✔
791
  }
792

793
  const auto iterator = string_table_.find(string_table_index);
1✔
794
  if (iterator == string_table_.end()) {
1✔
795
    throw std::invalid_argument("String table index not defined.");
×
796
  }
797

798
  const size_t size = iterator->second.size();
1✔
799
  for (uint32_t idx = 0; idx < size; ++idx) {
6✔
800
    setVariableValueInternal(start_variable_index + static_cast<int32_t>(idx),
5✔
801
                             follow_links,
802
                             static_cast<int32_t>(iterator->second.at(idx)));
5✔
803
  }
804
}
1✔
805

806
void VmSession::terminateWithVariableReturnCode(int32_t variable_index, bool follow_links) {
1,460✔
807
  const auto return_code =
808
      static_cast<int8_t>(getVariableValueInternal(variable_index, follow_links));
1,460✔
809
  runtime_statistics_.return_code = return_code;
1,423✔
810
  runtime_statistics_.terminated = true;
1,423✔
811
}
1,423✔
812

813
void VmSession::variableBitShiftVariableLeft(int32_t variable_index, bool follow_links,
101✔
814
                                             int32_t places_variable_index,
815
                                             bool places_follow_links) {
816
  const auto places =
817
      static_cast<int8_t>(getVariableValueInternal(places_variable_index, places_follow_links));
101✔
818
  bitShiftVariable(variable_index, follow_links, places);
45✔
819
}
27✔
820

821
void VmSession::variableBitShiftVariableRight(int32_t variable_index, bool follow_links,
75✔
822
                                              int32_t places_variable_index,
823
                                              bool places_follow_links) {
824
  const auto places =
825
      static_cast<int8_t>(getVariableValueInternal(places_variable_index, places_follow_links));
75✔
826
  bitShiftVariable(variable_index, follow_links, static_cast<int8_t>(-places));
40✔
827
}
38✔
828

829
void VmSession::variableRotateVariableLeft(int32_t variable_index, bool follow_links,
300✔
830
                                           int32_t places_variable_index,
831
                                           bool places_follow_links) {
832
  const auto places =
833
      static_cast<int8_t>(getVariableValueInternal(places_variable_index, places_follow_links));
300✔
834
  rotateVariable(variable_index, follow_links, places);
271✔
835
}
250✔
836

837
void VmSession::variableRotateVariableRight(int32_t variable_index, bool follow_links,
514✔
838
                                            int32_t places_variable_index,
839
                                            bool places_follow_links) {
840
  const auto places =
841
      static_cast<int8_t>(getVariableValueInternal(places_variable_index, places_follow_links));
514✔
842
  rotateVariable(variable_index, follow_links, static_cast<int8_t>(-places));
507✔
843
}
495✔
844

845
void VmSession::compareIfVariableGtConstant(int32_t variable_index, bool follow_links,
272✔
846
                                            int32_t constant, int32_t target_variable_index,
847
                                            bool target_follow_links) {
848
  const int32_t value = getVariableValueInternal(variable_index, follow_links);
272✔
849
  setVariableValueInternal(
252✔
850
      target_variable_index, target_follow_links, value > constant ? 0x1 : 0x0);
851
}
224✔
852

853
void VmSession::compareIfVariableLtConstant(int32_t variable_index, bool follow_links,
323✔
854
                                            int32_t constant, int32_t target_variable_index,
855
                                            bool target_follow_links) {
856
  const int32_t value = getVariableValueInternal(variable_index, follow_links);
323✔
857
  setVariableValueInternal(
285✔
858
      target_variable_index, target_follow_links, value < constant ? 0x1 : 0x0);
859
}
283✔
860

861
void VmSession::compareIfVariableEqConstant(int32_t variable_index, bool follow_links,
90✔
862
                                            int32_t constant, int32_t target_variable_index,
863
                                            bool target_follow_links) {
864
  const int32_t value = getVariableValueInternal(variable_index, follow_links);
90✔
865
  setVariableValueInternal(
66✔
866
      target_variable_index, target_follow_links, value == constant ? 0x1 : 0x0);
867
}
35✔
868

869
void VmSession::compareIfVariableGtVariable(int32_t variable_index_a, bool follow_links_a,
276✔
870
                                            int32_t variable_index_b, bool follow_links_b,
871
                                            int32_t target_variable_index,
872
                                            bool target_follow_links) {
873
  const int32_t value_a = getVariableValueInternal(variable_index_a, follow_links_a);
276✔
874
  const int32_t value_b = getVariableValueInternal(variable_index_b, follow_links_b);
264✔
875
  setVariableValueInternal(
241✔
876
      target_variable_index, target_follow_links, value_a > value_b ? 0x1 : 0x0);
877
}
240✔
878

879
void VmSession::compareIfVariableLtVariable(int32_t variable_index_a, bool follow_links_a,
35✔
880
                                            int32_t variable_index_b, bool follow_links_b,
881
                                            int32_t target_variable_index,
882
                                            bool target_follow_links) {
883
  const int32_t value_a = getVariableValueInternal(variable_index_a, follow_links_a);
35✔
884
  const int32_t value_b = getVariableValueInternal(variable_index_b, follow_links_b);
20✔
885
  setVariableValueInternal(
18✔
886
      target_variable_index, target_follow_links, value_a < value_b ? 0x1 : 0x0);
887
}
16✔
888

889
void VmSession::compareIfVariableEqVariable(int32_t variable_index_a, bool follow_links_a,
385✔
890
                                            int32_t variable_index_b, bool follow_links_b,
891
                                            int32_t target_variable_index,
892
                                            bool target_follow_links) {
893
  const int32_t value_a = getVariableValueInternal(variable_index_a, follow_links_a);
385✔
894
  const int32_t value_b = getVariableValueInternal(variable_index_b, follow_links_b);
346✔
895
  setVariableValueInternal(
325✔
896
      target_variable_index, target_follow_links, value_a == value_b ? 0x1 : 0x0);
897
}
309✔
898

899
void VmSession::getMaxOfVariableAndConstant(int32_t variable_index, bool follow_links,
256✔
900
                                            int32_t constant, int32_t target_variable_index,
901
                                            bool target_follow_links) {
902
  const int32_t value = getVariableValueInternal(variable_index, follow_links);
256✔
903
  setVariableValueInternal(
237✔
904
      target_variable_index, target_follow_links, value > constant ? value : constant);
237✔
905
}
231✔
906

907
void VmSession::getMinOfVariableAndConstant(int32_t variable_index, bool follow_links,
620✔
908
                                            int32_t constant, int32_t target_variable_index,
909
                                            bool target_follow_links) {
910
  const int32_t value = getVariableValueInternal(variable_index, follow_links);
620✔
911
  setVariableValueInternal(
611✔
912
      target_variable_index, target_follow_links, value < constant ? value : constant);
611✔
913
}
605✔
914

915
void VmSession::getMaxOfVariableAndVariable(int32_t variable_index_a, bool follow_links_a,
100✔
916
                                            int32_t variable_index_b, bool follow_links_b,
917
                                            int32_t target_variable_index,
918
                                            bool target_follow_links) {
919
  const int32_t value_a = getVariableValueInternal(variable_index_a, follow_links_a);
100✔
920
  const int32_t value_b = getVariableValueInternal(variable_index_b, follow_links_b);
90✔
921
  setVariableValueInternal(
90✔
922
      target_variable_index, target_follow_links, value_a > value_b ? value_a : value_b);
923
}
89✔
924

925
void VmSession::getMinOfVariableAndVariable(int32_t variable_index_a, bool follow_links_a,
102✔
926
                                            int32_t variable_index_b, bool follow_links_b,
927
                                            int32_t target_variable_index,
928
                                            bool target_follow_links) {
929
  const int32_t value_a = getVariableValueInternal(variable_index_a, follow_links_a);
102✔
930
  const int32_t value_b = getVariableValueInternal(variable_index_b, follow_links_b);
85✔
931
  setVariableValueInternal(
68✔
932
      target_variable_index, target_follow_links, value_a < value_b ? value_a : value_b);
933
}
61✔
934

935
void VmSession::printVariable(int32_t variable_index, bool follow_links, bool as_char) {
216✔
936
  appendVariableToPrintBuffer(variable_index, follow_links, as_char);
216✔
937
}
210✔
938

939
void VmSession::printStringFromStringTable(int32_t string_table_index) {
78✔
940
  appendToPrintBuffer(getStringTableEntry(string_table_index));
78✔
941
}
8✔
942

943
} // namespace beast
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