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

dedicate-project / beast / 981fd347-025e-489d-b66a-c1bd1b057f5f

pending completion
981fd347-025e-489d-b66a-c1bd1b057f5f

Pull #9

circleci

fairlight1337
Fixed a connection buffer size bug and added conn visualization
Pull Request #9: Adding pipeline applications

1225 of 1225 new or added lines in 24 files covered. (100.0%)

2854 of 3071 relevant lines covered (92.93%)

15664.12 hits per line

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

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

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

29
void VmSession::resetRuntimeStatistics() noexcept { runtime_statistics_ = RuntimeStatistics{}; }
8,701✔
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) {
44,378✔
44
  VariableDescriptor descriptor({Program::VariableType::Int32, behavior, false});
44,378✔
45
  variables_[variable_index] = std::make_pair(descriptor, 0);
44,378✔
46
}
44,378✔
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) {
51,247✔
58
  const auto iterator = variables_.find(getRealVariableIndex(variable_index, follow_links));
51,247✔
59
  if (iterator == variables_.end()) {
51,205✔
60
    throw std::invalid_argument("Variable index not declared");
×
61
  }
62
  if (iterator->second.first.behavior != VariableIoBehavior::Output) {
51,205✔
63
    throw std::invalid_argument("Variable behavior not declared as output");
2✔
64
  }
65
  return iterator->second.first.changed_since_last_interaction;
51,203✔
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() {
56,565✔
73
  int32_t data = program_.getData4(pointer_);
56,565✔
74
  pointer_ += 4;
56,548✔
75
  return data;
56,548✔
76
}
77

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

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

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

98
int32_t VmSession::getVariableValueInternal(int32_t variable_index, bool follow_links) {
29,471✔
99
  auto& [variable, value] = variables_[getRealVariableIndex(variable_index, follow_links)];
29,471✔
100
  if (variable.behavior == VariableIoBehavior::Input) {
26,838✔
101
    variable.changed_since_last_interaction = false;
11,854✔
102
  }
103
  return value;
26,838✔
104
}
105

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

114
void VmSession::setVariableValueInternal(int32_t variable_index, bool follow_links, int32_t value) {
19,832✔
115
  auto& [variable, current_value] = variables_[getRealVariableIndex(variable_index, follow_links)];
19,832✔
116
  if (variable.behavior == VariableIoBehavior::Output) {
18,797✔
117
    variable.changed_since_last_interaction = true;
11,783✔
118
  }
119
  current_value = value;
18,797✔
120
}
18,797✔
121

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

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

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

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

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

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

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

151
int32_t VmSession::getRealVariableIndex(int32_t variable_index, bool follow_links) {
136,062✔
152
  std::set<int32_t> visited_indices;
139,937✔
153
  std::map<int32_t, std::pair<VariableDescriptor, int32_t>>::iterator iterator;
136,062✔
154

155
  while ((iterator = variables_.find(variable_index)) != variables_.end()) {
136,315✔
156
    if (iterator->second.first.type != Program::VariableType::Link || !follow_links) {
132,440✔
157
      // This is a non-link variable, return it.
158
      return variable_index;
264,374✔
159
    }
160

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

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

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

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

189
  variables_.erase(variable_index);
62✔
190
}
62✔
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) {
97✔
214
  if (print_buffer_.size() + string.size() > maximum_print_buffer_length_) {
97✔
215
    throw std::overflow_error("Print buffer overflow.");
1✔
216
  }
217
  print_buffer_ += string;
96✔
218
}
96✔
219

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

486
void VmSession::loadStringItemLengthIntoVariable(int32_t string_table_index, int32_t variable_index,
80✔
487
                                                 bool follow_links) {
488
  if (string_table_index < 0 || string_table_index >= string_table_count_) {
80✔
489
    throw std::out_of_range("String table index out of bounds.");
78✔
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,
194✔
497
                                            int32_t start_variable_index, bool follow_links) {
498
  if (string_table_index < 0 || string_table_index >= string_table_count_) {
194✔
499
    throw std::out_of_range("String table index out of bounds.");
192✔
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,
112✔
516
                                  bool follow_links) {
517
  if (major_code == 0) { // Time and date related functions
112✔
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: " +
206✔
605
                                std::to_string(major_code));
309✔
606
  }
607
}
9✔
608

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

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

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

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

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

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

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

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

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

675
void VmSession::rotateVariable(int32_t variable_index, bool follow_links, int8_t places) {
2,014✔
676
  const auto value = static_cast<uint32_t>(getVariableValueInternal(variable_index, follow_links));
2,014✔
677
  const auto abs_places = static_cast<uint8_t>(std::abs(places));
1,885✔
678
  if (places < 0) {
1,885✔
679
    // Rotate right
680
    const uint32_t result =
1,045✔
681
        (value >> abs_places) | (value << static_cast<uint32_t>(32 - abs_places));
1,045✔
682
    setVariableValueInternal(variable_index, follow_links, static_cast<int32_t>(result));
1,045✔
683
  } else {
684
    // Rotate left
685
    const uint32_t result =
840✔
686
        (value << abs_places) | (value >> static_cast<uint32_t>(32 - abs_places));
840✔
687
    setVariableValueInternal(variable_index, follow_links, static_cast<int32_t>(result));
840✔
688
  }
689
}
1,885✔
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);
57✔
696
  setVariableValueInternal(
30✔
697
      stack_variable_index + 1 + current_stack_size, stack_follow_links, new_value);
30✔
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,
78✔
702
                                    int32_t constant) {
703
  const int32_t current_stack_size =
704
      getVariableValueInternal(stack_variable_index, stack_follow_links);
78✔
705
  setVariableValueInternal(
28✔
706
      stack_variable_index + 1 + current_stack_size, stack_follow_links, constant);
28✔
707
  setVariableValueInternal(stack_variable_index, stack_follow_links, current_stack_size + 1);
4✔
708
}
4✔
709

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

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

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

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

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

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

769
void VmSession::loadVariableStringItemLengthIntoVariable(int32_t string_item_variable_index,
169✔
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);
169✔
775
  if (string_table_index < 0 || string_table_index >= string_table_count_) {
87✔
776
    throw std::out_of_range("String table index out of bounds.");
85✔
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,
112✔
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);
112✔
789
  if (string_table_index < 0 || string_table_index >= string_table_count_) {
93✔
790
    throw std::out_of_range("String table index out of bounds.");
92✔
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) {
354✔
807
  const auto return_code =
808
      static_cast<int8_t>(getVariableValueInternal(variable_index, follow_links));
354✔
809
  runtime_statistics_.return_code = return_code;
321✔
810
  runtime_statistics_.terminated = true;
321✔
811
}
321✔
812

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

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

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

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

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

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

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

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

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

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

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

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

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

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

935
void VmSession::printVariable(int32_t variable_index, bool follow_links, bool as_char) {
137✔
936
  appendVariableToPrintBuffer(variable_index, follow_links, as_char);
137✔
937
}
86✔
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