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

dedicate-project / beast / 5769674b-2abc-4901-862a-bb80b2dc41c5

pending completion
5769674b-2abc-4901-862a-bb80b2dc41c5

Pull #9

circleci

fairlight1337
Introduced metrics functions for pipelines
Pull Request #9: Adding pipeline applications

1281 of 1281 new or added lines in 23 files covered. (100.0%)

2873 of 3126 relevant lines covered (91.91%)

14977.35 hits per line

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

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

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

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

14
namespace beast {
15

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

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

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

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

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

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

98
int32_t VmSession::getVariableValueInternal(int32_t variable_index, bool follow_links) {
57,275✔
99
  auto& [variable, value] = variables_[getRealVariableIndex(variable_index, follow_links)];
57,275✔
100
  if (variable.behavior == VariableIoBehavior::Input) {
55,688✔
101
    variable.changed_since_last_interaction = false;
17,564✔
102
  }
103
  return value;
55,688✔
104
}
105

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

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

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

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

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

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

151
int32_t VmSession::getRealVariableIndex(int32_t variable_index, bool follow_links) {
161,290✔
152
  std::set<int32_t> visited_indices;
163,814✔
153
  std::map<int32_t, std::pair<VariableDescriptor, int32_t>>::iterator iterator;
161,290✔
154

155
  while ((iterator = variables_.find(variable_index)) != variables_.end()) {
161,552✔
156
    if (iterator->second.first.type != Program::VariableType::Link || !follow_links) {
159,028✔
157
      // This is a non-link variable, return it.
158
      return variable_index;
317,532✔
159
    }
160

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

710
void VmSession::popVariableFromStack(int32_t stack_variable_index, bool stack_follow_links,
73✔
711
                                     int32_t variable_index, bool follow_links) {
712
  const int32_t current_stack_size =
713
      getVariableValueInternal(stack_variable_index, stack_follow_links);
73✔
714
  if (current_stack_size == 0) {
70✔
715
    throw std::underflow_error("Cannot pop value from stack, stack empty.");
52✔
716
  }
717
  const int32_t last_value = getVariableValueInternal(
24✔
718
      stack_variable_index + 1 + current_stack_size - 1, stack_follow_links);
18✔
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) {
49✔
724
  const int32_t current_stack_size =
725
      getVariableValueInternal(stack_variable_index, stack_follow_links);
49✔
726
  if (current_stack_size == 0) {
41✔
727
    throw std::underflow_error("Cannot pop value from stack, stack empty.");
11✔
728
  }
729
  setVariableValueInternal(stack_variable_index, true, current_stack_size - 1);
30✔
730
}
30✔
731

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

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

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

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

769
void VmSession::loadVariableStringItemLengthIntoVariable(int32_t string_item_variable_index,
26✔
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);
26✔
775
  if (string_table_index < 0 || string_table_index >= string_table_count_) {
9✔
776
    throw std::out_of_range("String table index out of bounds.");
7✔
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,
36✔
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);
36✔
789
  if (string_table_index < 0 || string_table_index >= string_table_count_) {
11✔
790
    throw std::out_of_range("String table index out of bounds.");
10✔
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) {
484✔
807
  const auto return_code =
808
      static_cast<int8_t>(getVariableValueInternal(variable_index, follow_links));
484✔
809
  runtime_statistics_.return_code = return_code;
466✔
810
  runtime_statistics_.terminated = true;
466✔
811
}
466✔
812

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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