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

dedicate-project / beast / 83ba6ee4-64d8-4300-bcbc-007a3bb86324

pending completion
83ba6ee4-64d8-4300-bcbc-007a3bb86324

Pull #9

circleci

fairlight1337
Large block of Doxygen comments added
Pull Request #9: Adding pipeline applications

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

2837 of 3042 relevant lines covered (93.26%)

13117.4 hits per line

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

96.39
/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,
3,243✔
17
                     size_t max_string_size)
3,243✔
18
    : program_{std::move(program)}, variable_count_{variable_count},
3,243✔
19
      string_table_count_{string_table_count}, max_string_size_{max_string_size} {
3,243✔
20
  resetRuntimeStatistics();
3,243✔
21
}
3,243✔
22

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

29
void VmSession::resetRuntimeStatistics() noexcept { runtime_statistics_ = RuntimeStatistics{}; }
3,249✔
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) {
14,822✔
44
  VariableDescriptor descriptor({Program::VariableType::Int32, behavior, false});
14,822✔
45
  variables_[variable_index] = std::make_pair(descriptor, 0);
14,822✔
46
}
14,822✔
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) {
18,973✔
58
  const auto iterator = variables_.find(getRealVariableIndex(variable_index, follow_links));
18,973✔
59
  if (iterator == variables_.end()) {
18,956✔
60
    throw std::invalid_argument("Variable index not declared");
×
61
  }
62
  if (iterator->second.first.behavior != VariableIoBehavior::Output) {
18,956✔
63
    throw std::invalid_argument("Variable behavior not declared as output");
2✔
64
  }
65
  return iterator->second.first.changed_since_last_interaction;
18,954✔
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() {
25,695✔
73
  int32_t data = program_.getData4(pointer_);
25,695✔
74
  pointer_ += 4;
25,687✔
75
  return data;
25,687✔
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() {
41,733✔
85
  int8_t data = program_.getData1(pointer_);
41,733✔
86
  pointer_ += 1;
41,728✔
87
  return data;
41,728✔
88
}
89

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

98
int32_t VmSession::getVariableValueInternal(int32_t variable_index, bool follow_links) {
16,864✔
99
  auto& [variable, value] = variables_[getRealVariableIndex(variable_index, follow_links)];
16,864✔
100
  if (variable.behavior == VariableIoBehavior::Input) {
15,751✔
101
    variable.changed_since_last_interaction = false;
5,463✔
102
  }
103
  return value;
15,751✔
104
}
105

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

114
void VmSession::setVariableValueInternal(int32_t variable_index, bool follow_links, int32_t value) {
6,343✔
115
  auto& [variable, current_value] = variables_[getRealVariableIndex(variable_index, follow_links)];
6,343✔
116
  if (variable.behavior == VariableIoBehavior::Output) {
5,967✔
117
    variable.changed_since_last_interaction = true;
3,501✔
118
  }
119
  current_value = value;
5,967✔
120
}
5,967✔
121

122
bool VmSession::isAtEnd() const noexcept {
16,423✔
123
  return runtime_statistics_.terminated || pointer_ >= program_.getSize();
16,423✔
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) {
226✔
129
  if (variable_index < 0 || variable_index >= variable_count_) {
226✔
130
    throw std::out_of_range("Invalid variable index.");
5✔
131
  }
132

133
  if (variable_type != Program::VariableType::Int32 &&
221✔
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()) {
221✔
139
    throw std::invalid_argument("Variable index already declared.");
14✔
140
  }
141

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

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

151
int32_t VmSession::getRealVariableIndex(int32_t variable_index, bool follow_links) {
54,010✔
152
  std::set<int32_t> visited_indices;
55,614✔
153
  std::map<int32_t, std::pair<VariableDescriptor, int32_t>>::iterator iterator;
54,010✔
154

155
  while ((iterator = variables_.find(variable_index)) != variables_.end()) {
54,257✔
156
    if (iterator->second.first.type != Program::VariableType::Link || !follow_links) {
52,653✔
157
      // This is a non-link variable, return it.
158
      return variable_index;
104,812✔
159
    }
160

161
    if (iterator->second.first.type == Program::VariableType::Link) {
247✔
162
      if (visited_indices.find(variable_index) != visited_indices.end()) {
247✔
163
        throw std::invalid_argument("Circular variable index link.");
×
164
      }
165
      visited_indices.insert(variable_index);
247✔
166
      variable_index = getVariableValueInternal(variable_index, false);
247✔
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.");
1,604✔
174
}
175

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

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

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

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

192
void VmSession::setStringTableEntry(int32_t string_table_index, std::string_view string_content) {
99✔
193
  if (string_table_index < 0 || string_table_index >= string_table_count_) {
99✔
194
    throw std::out_of_range("String table index out of bounds.");
83✔
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 {
59✔
205
  const auto iterator = string_table_.find(string_table_index);
59✔
206
  if (iterator == string_table_.end()) {
59✔
207
    throw std::out_of_range("String table index out of bounds.");
49✔
208
  }
209

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

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

220
void VmSession::appendVariableToPrintBuffer(int32_t variable_index, bool follow_links,
322✔
221
                                            bool as_char) {
222
  variable_index = getRealVariableIndex(variable_index, follow_links);
322✔
223
  if (variables_[variable_index].first.type == Program::VariableType::Int32) {
298✔
224
    if (as_char) {
298✔
225
      const uint32_t flag = 0xff;
274✔
226
      const auto val = static_cast<char>(
227
          static_cast<uint32_t>(getVariableValueInternal(variable_index, false)) & flag);
274✔
228
      appendToPrintBuffer(std::string_view(&val, 1));
274✔
229
    } else {
230
      appendToPrintBuffer(std::to_string(getVariableValueInternal(variable_index, false)));
24✔
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
}
298✔
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) {
313✔
247
  runtime_statistics_.return_code = return_code;
313✔
248
  runtime_statistics_.terminated = true;
313✔
249
}
313✔
250

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

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

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

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

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

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

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

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

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

328
void VmSession::absoluteJumpToVariableAddressIfVariableEq0(int32_t condition_variable,
1,449✔
329
                                                           bool follow_condition_links,
330
                                                           int32_t addr_variable,
331
                                                           bool follow_addr_links) {
332
  if (getVariableValueInternal(condition_variable, follow_condition_links) == 0) {
1,449✔
333
    pointer_ = getVariableValueInternal(addr_variable, follow_addr_links);
1,443✔
334
  }
335
}
1,445✔
336

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

460
void VmSession::loadRandomValueIntoVariable(int32_t variable_index, bool follow_links) {
819✔
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;
819✔
466
  std::random_device random_device;
1,638✔
467
  rng.seed(random_device());
819✔
468
  std::uniform_int_distribution<int32_t> distribution;
819✔
469
  setVariableValueInternal(variable_index, follow_links, distribution(rng));
819✔
470
}
790✔
471

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

474
void VmSession::unconditionalJumpToAbsoluteVariableAddress(int32_t variable_index,
2,098✔
475
                                                           bool follow_links) {
476
  pointer_ = getVariableValueInternal(variable_index, follow_links);
2,098✔
477
}
2,095✔
478

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

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

486
void VmSession::loadStringItemLengthIntoVariable(int32_t string_table_index, int32_t variable_index,
7✔
487
                                                 bool follow_links) {
488
  if (string_table_index < 0 || string_table_index >= string_table_count_) {
7✔
489
    throw std::out_of_range("String table index out of bounds.");
5✔
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,
59✔
497
                                            int32_t start_variable_index, bool follow_links) {
498
  if (string_table_index < 0 || string_table_index >= string_table_count_) {
59✔
499
    throw std::out_of_range("String table index out of bounds.");
57✔
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,
40✔
516
                                  bool follow_links) {
517
  if (major_code == 0) { // Time and date related functions
40✔
518
    // Get the current UTC time
519
    const auto now_utc = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
11✔
520
    std::tm utc_tm{};
11✔
521
    if (gmtime_r(&now_utc, &utc_tm) == nullptr) {
11✔
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());
11✔
527
    std::tm local_tm{};
11✔
528
    if (localtime_r(&now_local, &local_tm) == nullptr) {
11✔
529
      throw std::domain_error("Time conversion failed.");
×
530
    }
531

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

535
    switch (minor_code) {
11✔
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:
2✔
600
      throw std::invalid_argument("Unknown major/minor code combination for system call: " +
2✔
601
                                  std::to_string(major_code) + ", " + std::to_string(minor_code));
4✔
602
    }
603
  } else {
604
    throw std::invalid_argument("Unknown major code for system call: " +
58✔
605
                                std::to_string(major_code));
87✔
606
  }
607
}
9✔
608

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

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

622
void VmSession::bitWiseAndTwoVariables(int32_t variable_index_a, bool follow_links_a,
26✔
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));
26✔
626
  const auto value_b =
627
      static_cast<uint32_t>(getVariableValueInternal(variable_index_b, follow_links_b));
18✔
628
  const uint32_t result = value_a & value_b;
7✔
629
  setVariableValueInternal(variable_index_b, follow_links_b, static_cast<int32_t>(result));
7✔
630
}
7✔
631

632
void VmSession::bitWiseOrTwoVariables(int32_t variable_index_a, bool follow_links_a,
43✔
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));
43✔
636
  const auto value_b =
637
      static_cast<uint32_t>(getVariableValueInternal(variable_index_b, follow_links_b));
21✔
638
  const uint32_t result = value_a | value_b;
19✔
639
  setVariableValueInternal(variable_index_b, follow_links_b, static_cast<int32_t>(result));
19✔
640
}
19✔
641

642
void VmSession::bitWiseXorTwoVariables(int32_t variable_index_a, bool follow_links_a,
628✔
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));
628✔
646
  const auto value_b =
647
      static_cast<uint32_t>(getVariableValueInternal(variable_index_b, follow_links_b));
617✔
648
  const uint32_t result = value_a ^ value_b;
612✔
649
  setVariableValueInternal(variable_index_b, follow_links_b, static_cast<int32_t>(result));
612✔
650
}
612✔
651

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

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

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

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

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

691
void VmSession::pushVariableOnStack(int32_t stack_variable_index, bool stack_follow_links,
82✔
692
                                    int32_t variable_index, bool follow_links) {
693
  const int32_t current_stack_size =
694
      getVariableValueInternal(stack_variable_index, stack_follow_links);
82✔
695
  const int32_t new_value = getVariableValueInternal(variable_index, follow_links);
37✔
696
  setVariableValueInternal(
33✔
697
      stack_variable_index + 1 + current_stack_size, stack_follow_links, new_value);
33✔
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,
95✔
702
                                    int32_t constant) {
703
  const int32_t current_stack_size =
704
      getVariableValueInternal(stack_variable_index, stack_follow_links);
95✔
705
  setVariableValueInternal(
92✔
706
      stack_variable_index + 1 + current_stack_size, stack_follow_links, constant);
92✔
707
  setVariableValueInternal(stack_variable_index, stack_follow_links, current_stack_size + 1);
84✔
708
}
84✔
709

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

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

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

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

746
void VmSession::setVariableStringTableEntry(int32_t variable_index, bool follow_links,
22✔
747
                                            std::string_view string_content) {
748
  const int32_t string_table_index = getVariableValueInternal(variable_index, follow_links);
22✔
749
  if (string_table_index < 0 || string_table_index >= string_table_count_) {
10✔
750
    throw std::out_of_range("String table index out of bounds.");
8✔
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) {
43✔
761
  const int32_t string_table_index = getVariableValueInternal(variable_index, follow_links);
43✔
762
  if (string_table_index < 0 || string_table_index >= string_table_count_) {
39✔
763
    throw std::out_of_range("String table index out of bounds.");
38✔
764
  }
765

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

769
void VmSession::loadVariableStringItemLengthIntoVariable(int32_t string_item_variable_index,
29✔
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);
29✔
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,
103✔
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);
103✔
789
  if (string_table_index < 0 || string_table_index >= string_table_count_) {
76✔
790
    throw std::out_of_range("String table index out of bounds.");
75✔
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) {
880✔
807
  const auto return_code =
808
      static_cast<int8_t>(getVariableValueInternal(variable_index, follow_links));
880✔
809
  runtime_statistics_.return_code = return_code;
872✔
810
  runtime_statistics_.terminated = true;
872✔
811
}
872✔
812

813
void VmSession::variableBitShiftVariableLeft(int32_t variable_index, bool follow_links,
54✔
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));
54✔
818
  bitShiftVariable(variable_index, follow_links, places);
45✔
819
}
41✔
820

821
void VmSession::variableBitShiftVariableRight(int32_t variable_index, bool follow_links,
242✔
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));
242✔
826
  bitShiftVariable(variable_index, follow_links, static_cast<int8_t>(-places));
241✔
827
}
212✔
828

829
void VmSession::variableRotateVariableLeft(int32_t variable_index, bool follow_links,
17✔
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));
17✔
834
  rotateVariable(variable_index, follow_links, places);
10✔
835
}
10✔
836

837
void VmSession::variableRotateVariableRight(int32_t variable_index, bool follow_links,
123✔
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));
123✔
842
  rotateVariable(variable_index, follow_links, static_cast<int8_t>(-places));
116✔
843
}
56✔
844

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

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

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

869
void VmSession::compareIfVariableGtVariable(int32_t variable_index_a, bool follow_links_a,
87✔
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);
87✔
874
  const int32_t value_b = getVariableValueInternal(variable_index_b, follow_links_b);
84✔
875
  setVariableValueInternal(
84✔
876
      target_variable_index, target_follow_links, value_a > value_b ? 0x1 : 0x0);
877
}
83✔
878

879
void VmSession::compareIfVariableLtVariable(int32_t variable_index_a, bool follow_links_a,
41✔
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);
41✔
884
  const int32_t value_b = getVariableValueInternal(variable_index_b, follow_links_b);
35✔
885
  setVariableValueInternal(
27✔
886
      target_variable_index, target_follow_links, value_a < value_b ? 0x1 : 0x0);
887
}
27✔
888

889
void VmSession::compareIfVariableEqVariable(int32_t variable_index_a, bool follow_links_a,
23✔
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);
23✔
894
  const int32_t value_b = getVariableValueInternal(variable_index_b, follow_links_b);
9✔
895
  setVariableValueInternal(
9✔
896
      target_variable_index, target_follow_links, value_a == value_b ? 0x1 : 0x0);
897
}
7✔
898

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

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

915
void VmSession::getMaxOfVariableAndVariable(int32_t variable_index_a, bool follow_links_a,
37✔
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);
37✔
920
  const int32_t value_b = getVariableValueInternal(variable_index_b, follow_links_b);
32✔
921
  setVariableValueInternal(
21✔
922
      target_variable_index, target_follow_links, value_a > value_b ? value_a : value_b);
923
}
19✔
924

925
void VmSession::getMinOfVariableAndVariable(int32_t variable_index_a, bool follow_links_a,
269✔
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);
269✔
930
  const int32_t value_b = getVariableValueInternal(variable_index_b, follow_links_b);
264✔
931
  setVariableValueInternal(
209✔
932
      target_variable_index, target_follow_links, value_a < value_b ? value_a : value_b);
933
}
206✔
934

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

939
void VmSession::printStringFromStringTable(int32_t string_table_index) {
58✔
940
  appendToPrintBuffer(getStringTableEntry(string_table_index));
58✔
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