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

dedicate-project / beast / 73f13f56-4c3c-4b62-82a6-0cb063505418

pending completion
73f13f56-4c3c-4b62-82a6-0cb063505418

push

circleci

fairlight1337
Fix code smells

63 of 63 new or added lines in 3 files covered. (100.0%)

1788 of 1875 relevant lines covered (95.36%)

65.85 hits per line

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

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

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

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

13
namespace beast {
14

15
VmSession::VmSession(
82✔
16
    Program program, size_t variable_count, size_t string_table_count,
17
    size_t max_string_size)
82✔
18
  : program_{std::move(program)}, variable_count_{variable_count}
82✔
19
  , string_table_count_{string_table_count}, max_string_size_{max_string_size} {
82✔
20
}
82✔
21

22
void VmSession::setVariableBehavior(int32_t variable_index, VariableIoBehavior behavior) {
14✔
23
  VariableDescriptor descriptor({Program::VariableType::Int32, behavior, false});
14✔
24
  variables_[variable_index] = std::make_pair(descriptor, 0);
14✔
25
}
14✔
26

27
VmSession::VariableIoBehavior VmSession::getVariableBehavior(
×
28
    int32_t variable_index, bool follow_links) {
29
  const auto iterator = variables_.find(getRealVariableIndex(variable_index, follow_links));
×
30
  if (iterator == variables_.end()) {
×
31
    throw std::invalid_argument("Variable index not declared");
×
32
  }
33
  return iterator->second.first.behavior;
×
34
}
35

36
bool VmSession::hasOutputDataAvailable(int32_t variable_index, bool follow_links) {
×
37
  const auto iterator = variables_.find(getRealVariableIndex(variable_index, follow_links));
×
38
  if (iterator == variables_.end()) {
×
39
    throw std::invalid_argument("Variable index not declared");
×
40
  }
41
  if (iterator->second.first.behavior != VariableIoBehavior::Output) {
×
42
    throw std::invalid_argument("Variable behavior not declared as output");
×
43
  }
44
  return iterator->second.first.changed_since_last_interaction;
×
45
}
46

47
void VmSession::setMaximumPrintBufferLength(size_t maximum_print_buffer_length) {
×
48
  maximum_print_buffer_length_ = maximum_print_buffer_length;
×
49
}
×
50

51
int32_t VmSession::getData4() {
912✔
52
  int32_t data = program_.getData4(pointer_);
912✔
53
  pointer_ += 4;
912✔
54
  return data;
912✔
55
}
56

57
int16_t VmSession::getData2() {
17✔
58
  int16_t data = program_.getData2(pointer_);
17✔
59
  pointer_ += 2;
17✔
60
  return data;
17✔
61
}
62

63
int8_t VmSession::getData1() {
3,076✔
64
  int8_t data = program_.getData1(pointer_);
3,076✔
65
  pointer_ += 1;
3,075✔
66
  return data;
3,075✔
67
}
68

69
int32_t VmSession::getVariableValue(int32_t variable_index, bool follow_links) {
105✔
70
  auto& [variable, value] = variables_[getRealVariableIndex(variable_index, follow_links)];
105✔
71
  if (variable.behavior == VariableIoBehavior::Output) {
105✔
72
    variable.changed_since_last_interaction = false;
×
73
  }
74
  return value;
105✔
75
}
76

77
int32_t VmSession::getVariableValueInternal(int32_t variable_index, bool follow_links) {
173✔
78
  auto& [variable, value] = variables_[getRealVariableIndex(variable_index, follow_links)];
173✔
79
  if (variable.behavior == VariableIoBehavior::Input) {
173✔
80
    variable.changed_since_last_interaction = false;
×
81
  }
82
  return value;
173✔
83
}
84

85
void VmSession::setVariableValue(int32_t variable_index, bool follow_links, int32_t value) {
1✔
86
  auto& [variable, current_value] = variables_[getRealVariableIndex(variable_index, follow_links)];
1✔
87
  if (variable.behavior == VariableIoBehavior::Input) {
1✔
88
    variable.changed_since_last_interaction = true;
1✔
89
  }
90
  current_value = value;
1✔
91
}
1✔
92

93
void VmSession::setVariableValueInternal(int32_t variable_index, bool follow_links, int32_t value) {
339✔
94
  auto& [variable, current_value] = variables_[getRealVariableIndex(variable_index, follow_links)];
339✔
95
  if (variable.behavior == VariableIoBehavior::Output) {
338✔
96
    variable.changed_since_last_interaction = true;
×
97
  }
98
  current_value = value;
338✔
99
}
338✔
100

101
bool VmSession::isAtEnd() const {
2,304✔
102
  return was_terminated_ || pointer_ >= program_.getSize();
2,304✔
103
}
104

105
void VmSession::registerVariable(int32_t variable_index, Program::VariableType variable_type) {
195✔
106
  if (variable_index < 0 || variable_index >= variable_count_) {
195✔
107
    throw std::out_of_range("Invalid variable index.");
×
108
  }
109

110
  if (variable_type != Program::VariableType::Int32 &&
195✔
111
      variable_type != Program::VariableType::Link) {
112
    throw std::invalid_argument("Invalid declarative variable type.");
×
113
  }
114

115
  if (variables_.find(variable_index) != variables_.end()) {
195✔
116
    throw std::invalid_argument("Variable index already declared.");
×
117
  }
118

119
  if (variables_.size() == variable_count_) {
195✔
120
    // No more space for variables
121
    throw std::overflow_error("Variables cache full.");
×
122
  }
123

124
  VariableDescriptor descriptor({variable_type, VariableIoBehavior::Store, false});
195✔
125
  variables_[variable_index] = std::make_pair(descriptor, 0);
195✔
126
}
195✔
127

128
int32_t VmSession::getRealVariableIndex(int32_t variable_index, bool follow_links) {
630✔
129
  std::set<int32_t> visited_indices;
631✔
130
  std::map<int32_t, std::pair<VariableDescriptor, int32_t>>::iterator iterator;
630✔
131

132
  while ((iterator = variables_.find(variable_index)) != variables_.end()) {
631✔
133
    if (iterator->second.first.type != Program::VariableType::Link || !follow_links) {
630✔
134
      // This is a non-link variable, return it.
135
      return variable_index;
1,258✔
136
    }
137

138
    if (iterator->second.first.type == Program::VariableType::Link) {
1✔
139
      if (visited_indices.find(variable_index) != visited_indices.end()) {
1✔
140
        throw std::logic_error("Circular variable index link.");
×
141
      }
142
      visited_indices.insert(variable_index);
1✔
143
      variable_index = getVariableValueInternal(variable_index, false);
1✔
144
    } else {
145
      throw std::invalid_argument("Invalid declarative variable type.");
×
146
    }
147
  }
148

149
  // Undeclared variables cannot be set.
150
  throw std::invalid_argument("Variable index not declared.");
1✔
151
}
152

153
void VmSession::setVariable(int32_t variable_index, int32_t value, bool follow_links) {
192✔
154
  setVariableValueInternal(variable_index, follow_links, value);
192✔
155
}
191✔
156

157
void VmSession::unregisterVariable(int32_t variable_index) {
1✔
158
  if (variable_index < 0 || variable_index >= variable_count_) {
1✔
159
    throw std::out_of_range("Invalid variable index.");
×
160
  }
161

162
  if (variables_.find(variable_index) == variables_.end()) {
1✔
163
    throw std::invalid_argument("Variable index not declared, cannot undeclare.");
×
164
  }
165

166
  variables_.erase(variable_index);
1✔
167
}
1✔
168

169
void VmSession::setStringTableEntry(int32_t string_table_index, std::string_view string_content) {
15✔
170
  if (string_table_index < 0 || string_table_index >= string_table_count_) {
15✔
171
    throw std::out_of_range("String table index out of bounds.");
1✔
172
  }
173

174
  if (string_content.size() > max_string_size_) {
14✔
175
    throw std::length_error("String too long.");
×
176
  }
177

178
  string_table_[string_table_index] = string_content;
14✔
179
}
14✔
180

181
const std::string& VmSession::getStringTableEntry(int32_t string_table_index) const {
8✔
182
  const auto iterator = string_table_.find(string_table_index);
8✔
183
  if (iterator == string_table_.end()) {
8✔
184
    throw std::out_of_range("String table index out of bounds.");
×
185
  }
186

187
  return iterator->second;
8✔
188
}
189

190
void VmSession::appendToPrintBuffer(std::string_view string) {
13✔
191
  if (print_buffer_.size() + string.size() > maximum_print_buffer_length_) {
13✔
192
    throw std::overflow_error("Print buffer overflow.");
×
193
  }
194
  print_buffer_ += string;
13✔
195
}
13✔
196

197
void VmSession::appendVariableToPrintBuffer(
5✔
198
    int32_t variable_index, bool follow_links, bool as_char) {
199
  variable_index = getRealVariableIndex(variable_index, follow_links);
5✔
200
  if (variables_[variable_index].first.type == Program::VariableType::Int32) {
5✔
201
    if (as_char) {
5✔
202
      const uint32_t flag = 0xff;
5✔
203
      const auto val =
204
          static_cast<char>(
205
              static_cast<uint32_t>(getVariableValueInternal(variable_index, false)) & flag);
5✔
206
      appendToPrintBuffer(std::string_view(&val, 1));
5✔
207
    } else {
208
      appendToPrintBuffer(std::to_string(getVariableValueInternal(variable_index, false)));
×
209
    }
210
  } else if (variables_[variable_index].first.type == Program::VariableType::Link) {
×
211
    appendToPrintBuffer(
×
212
        "L{" + std::to_string(getVariableValueInternal(variable_index, false)) + "}");
×
213
  } else {
214
    throw std::invalid_argument("Cannot print unsupported variable type (" +
×
215
                                std::to_string(
×
216
                                    static_cast<int32_t>(variables_[variable_index].first.type))
×
217
                                + ").");
×
218
  }
219
}
5✔
220

221
const std::string& VmSession::getPrintBuffer() const {
9✔
222
  return print_buffer_;
9✔
223
}
224

225
void VmSession::clearPrintBuffer() {
×
226
  print_buffer_ = "";
×
227
}
×
228

229
void VmSession::terminate(int8_t return_code) {
1✔
230
  return_code_ = return_code;
1✔
231
  was_terminated_ = true;
1✔
232
}
1✔
233

234
int8_t VmSession::getReturnCode() const {
2✔
235
  return return_code_;
2✔
236
}
237

238
void VmSession::addConstantToVariable(int32_t variable_index, int32_t constant, bool follow_links) {
31✔
239
  setVariableValueInternal(
31✔
240
      variable_index, follow_links,
241
      getVariableValueInternal(variable_index, follow_links) + constant);
31✔
242
}
31✔
243

244
void VmSession::addVariableToVariable(
1✔
245
    int32_t source_variable, int32_t destination_variable, bool follow_source_links,
246
    bool follow_destination_links) {
247
  setVariableValueInternal(
1✔
248
      destination_variable, follow_destination_links,
249
      getVariableValueInternal(destination_variable, follow_destination_links) +
1✔
250
      getVariableValueInternal(source_variable, follow_source_links));
1✔
251
}
1✔
252

253
void VmSession::subtractConstantFromVariable(
7✔
254
    int32_t variable_index, int32_t constant, bool follow_links) {
255
  setVariableValueInternal(
7✔
256
      variable_index, follow_links,
257
      getVariableValueInternal(variable_index, follow_links) - constant);
7✔
258
}
7✔
259

260
void VmSession::subtractVariableFromVariable(
1✔
261
    int32_t source_variable, int32_t destination_variable, bool follow_source_links,
262
    bool follow_destination_links) {
263
  setVariableValueInternal(
1✔
264
      destination_variable, follow_destination_links,
265
      getVariableValueInternal(destination_variable, follow_destination_links) -
1✔
266
      getVariableValueInternal(source_variable, follow_source_links));
1✔
267
}
1✔
268

269
void VmSession::relativeJumpToVariableAddressIfVariableGt0(
2✔
270
    int32_t condition_variable, bool follow_condition_links,
271
    int32_t addr_variable, bool follow_addr_links) {
272
  if (getVariableValueInternal(condition_variable, follow_condition_links) > 0) {
2✔
273
    pointer_ += getVariableValueInternal(addr_variable, follow_addr_links);
1✔
274
  }
275
}
2✔
276

277
void VmSession::relativeJumpToVariableAddressIfVariableLt0(
2✔
278
    int32_t condition_variable, bool follow_condition_links,
279
    int32_t addr_variable, bool follow_addr_links) {
280
  if (getVariableValueInternal(condition_variable, follow_condition_links) < 0) {
2✔
281
    pointer_ += getVariableValueInternal(addr_variable, follow_addr_links);
1✔
282
  }
283
}
2✔
284

285
void VmSession::relativeJumpToVariableAddressIfVariableEq0(
2✔
286
    int32_t condition_variable, bool follow_condition_links,
287
    int32_t addr_variable, bool follow_addr_links) {
288
  if (getVariableValueInternal(condition_variable, follow_condition_links) == 0) {
2✔
289
    pointer_ += getVariableValueInternal(addr_variable, follow_addr_links);
1✔
290
  }
291
}
2✔
292

293
void VmSession::absoluteJumpToVariableAddressIfVariableGt0(
3✔
294
    int32_t condition_variable, bool follow_condition_links,
295
    int32_t addr_variable, bool follow_addr_links) {
296
  if (getVariableValueInternal(condition_variable, follow_condition_links) > 0) {
3✔
297
    pointer_ = getVariableValueInternal(addr_variable, follow_addr_links);
2✔
298
  }
299
}
3✔
300

301
void VmSession::absoluteJumpToVariableAddressIfVariableLt0(
4✔
302
    int32_t condition_variable, bool follow_condition_links,
303
    int32_t addr_variable, bool follow_addr_links) {
304
  if (getVariableValueInternal(condition_variable, follow_condition_links) < 0) {
4✔
305
    pointer_ = getVariableValueInternal(addr_variable, follow_addr_links);
3✔
306
  }
307
}
4✔
308

309
void VmSession::absoluteJumpToVariableAddressIfVariableEq0(
2✔
310
    int32_t condition_variable, bool follow_condition_links,
311
    int32_t addr_variable, bool follow_addr_links) {
312
  if (getVariableValueInternal(condition_variable, follow_condition_links) == 0) {
2✔
313
    pointer_ = getVariableValueInternal(addr_variable, follow_addr_links);
1✔
314
  }
315
}
2✔
316

317
void VmSession::relativeJumpToAddressIfVariableGt0(
2✔
318
    int32_t condition_variable, bool follow_condition_links, int32_t addr) {
319
  if (getVariableValueInternal(condition_variable, follow_condition_links) > 0) {
2✔
320
    pointer_ += addr;
1✔
321
  }
322
}
2✔
323

324
void VmSession::relativeJumpToAddressIfVariableLt0(
2✔
325
    int32_t condition_variable, bool follow_condition_links, int32_t addr) {
326
  if (getVariableValueInternal(condition_variable, follow_condition_links) < 0) {
2✔
327
    pointer_ += addr;
1✔
328
  }
329
}
2✔
330

331
void VmSession::relativeJumpToAddressIfVariableEq0(
2✔
332
    int32_t condition_variable, bool follow_condition_links, int32_t addr) {
333
  if (getVariableValueInternal(condition_variable, follow_condition_links) == 0) {
2✔
334
    pointer_ += addr;
1✔
335
  }
336
}
2✔
337

338
void VmSession::absoluteJumpToAddressIfVariableGt0(
3✔
339
    int32_t condition_variable, bool follow_condition_links, int32_t addr) {
340
  if (getVariableValueInternal(condition_variable, follow_condition_links) > 0) {
3✔
341
    pointer_ = addr;
2✔
342
  }
343
}
3✔
344

345
void VmSession::absoluteJumpToAddressIfVariableLt0(
4✔
346
    int32_t condition_variable, bool follow_condition_links, int32_t addr) {
347
  if (getVariableValueInternal(condition_variable, follow_condition_links) < 0) {
4✔
348
    pointer_ = addr;
3✔
349
  }
350
}
4✔
351

352
void VmSession::absoluteJumpToAddressIfVariableEq0(
2✔
353
    int32_t condition_variable, bool follow_condition_links, int32_t addr) {
354
  if (getVariableValueInternal(condition_variable, follow_condition_links) == 0) {
2✔
355
    pointer_ = addr;
1✔
356
  }
357
}
2✔
358

359
void VmSession::loadMemorySizeIntoVariable(int32_t variable, bool follow_links) {
1✔
360
  setVariableValueInternal(variable, follow_links, static_cast<int32_t>(variable_count_));
1✔
361
}
1✔
362

363
void VmSession::checkIfVariableIsInput(
2✔
364
    int32_t source_variable, bool follow_source_links,
365
    int32_t destination_variable, bool follow_destination_links) {
366
  setVariableValueInternal(
2✔
367
      destination_variable, follow_destination_links,
368
      variables_[getRealVariableIndex(source_variable, follow_source_links)].first.behavior
2✔
369
      == VmSession::VariableIoBehavior::Input ? 0x1 : 0x0);
370
}
2✔
371

372
void VmSession::checkIfVariableIsOutput(
2✔
373
    int32_t source_variable, bool follow_source_links,
374
    int32_t destination_variable, bool follow_destination_links) {
375
  setVariableValueInternal(
2✔
376
      destination_variable, follow_destination_links,
377
      variables_[getRealVariableIndex(source_variable, follow_source_links)].first.behavior
2✔
378
      == VmSession::VariableIoBehavior::Output ? 0x1 : 0x0);
379
}
2✔
380

381
void VmSession::copyVariable(
1✔
382
    int32_t source_variable, bool follow_source_links,
383
    int32_t destination_variable, bool follow_destination_links) {
384
  setVariableValueInternal(
1✔
385
      destination_variable, follow_destination_links,
386
      getVariableValueInternal(source_variable, follow_source_links));
387
}
1✔
388

389
void VmSession::loadInputCountIntoVariable(int32_t variable, bool follow_links) {
1✔
390
  int32_t input_count = 0;
1✔
391
  for (const auto& [index, variable_data] : variables_) {
7✔
392
    if (variable_data.first.behavior == VariableIoBehavior::Input) {
6✔
393
      input_count++;
2✔
394
    }
395
  }
396
  setVariableValueInternal(variable, follow_links, input_count);
1✔
397
}
1✔
398

399
void VmSession::loadOutputCountIntoVariable(int32_t variable, bool follow_links) {
1✔
400
  int32_t output_count = 0;
1✔
401
  for (const auto& [index, variable_data] : variables_) {
7✔
402
    if (variable_data.first.behavior == VariableIoBehavior::Output) {
6✔
403
      output_count++;
3✔
404
    }
405
  }
406
  setVariableValueInternal(variable, follow_links, output_count);
1✔
407
}
1✔
408

409
void VmSession::loadCurrentAddressIntoVariable(int32_t variable, bool follow_links) {
1✔
410
  setVariableValueInternal(variable, follow_links, pointer_);
1✔
411
}
1✔
412

413
void VmSession::checkIfInputWasSet(
3✔
414
    int32_t variable_index, bool follow_links,
415
    int32_t destination_variable, bool follow_destination_links) {
416
  auto& [variable, value] = variables_[getRealVariableIndex(variable_index, follow_links)];
3✔
417
  if (variable.behavior != VariableIoBehavior::Input) {
3✔
418
    throw std::invalid_argument("Variable is not an input.");
1✔
419
  }
420

421
  setVariableValueInternal(
2✔
422
      destination_variable, follow_destination_links,
423
      variable.changed_since_last_interaction ? 0x1 : 0x0);
2✔
424
  variable.changed_since_last_interaction = false;
2✔
425
}
2✔
426

427
void VmSession::loadStringTableLimitIntoVariable(int32_t variable_index, bool follow_links) {
1✔
428
  setVariableValueInternal(variable_index, follow_links, static_cast<int32_t>(string_table_count_));
1✔
429
}
1✔
430

431
void VmSession::loadStringTableItemLengthLimitIntoVariable(
1✔
432
    int32_t variable_index, bool follow_links) {
433
  setVariableValueInternal(variable_index, follow_links, static_cast<int32_t>(max_string_size_));
1✔
434
}
1✔
435

436
void VmSession::loadRandomValueIntoVariable(int32_t variable_index, bool follow_links) {
2✔
437
  // NOTE(fairlight1337): The initialization of the `rng` variable is not linted here to prevent
438
  // clang-tidy from complaining about seeding with a value from the default constructor. Since
439
  // we're using `random_device` to seed `rng` right after, this warning is discarded explicitly.
440
  // NOLINTNEXTLINE
441
  std::mt19937 rng;
2✔
442
  std::random_device random_device;
4✔
443
  rng.seed(random_device());
2✔
444
  std::uniform_int_distribution<int32_t> distribution;
2✔
445
  setVariableValueInternal(variable_index, follow_links, distribution(rng));
2✔
446
}
2✔
447

448
void VmSession::unconditionalJumpToAbsoluteAddress(int32_t addr) {
1✔
449
  pointer_ = addr;
1✔
450
}
1✔
451

452
void VmSession::unconditionalJumpToAbsoluteVariableAddress(
1✔
453
    int32_t variable_index, bool follow_links) {
454
  pointer_ = getVariableValueInternal(variable_index, follow_links);
1✔
455
}
1✔
456

457
void VmSession::unconditionalJumpToRelativeAddress(int32_t addr) {
1✔
458
  pointer_ += addr;
1✔
459
}
1✔
460

461
void VmSession::unconditionalJumpToRelativeVariableAddress(
1✔
462
    int32_t variable_index, bool follow_links) {
463
  pointer_ += getVariableValueInternal(variable_index, follow_links);
1✔
464
}
1✔
465

466
void VmSession::loadStringItemLengthIntoVariable(
3✔
467
    int32_t string_table_index, int32_t variable_index, bool follow_links) {
468
  if (string_table_index < 0 || string_table_index >= string_table_count_) {
3✔
469
    throw std::out_of_range("String table index out of bounds.");
1✔
470
  }
471

472
  setVariableValueInternal(
2✔
473
      variable_index, follow_links, static_cast<int32_t>(string_table_[string_table_index].size()));
2✔
474
}
2✔
475

476
void VmSession::loadStringItemIntoVariables(
2✔
477
    int32_t string_table_index, int32_t start_variable_index, bool follow_links) {
478
  if (string_table_index < 0 || string_table_index >= string_table_count_) {
2✔
479
    throw std::out_of_range("String table index out of bounds.");
×
480
  }
481

482
  const auto iterator = string_table_.find(string_table_index);
2✔
483
  if (iterator == string_table_.end()) {
2✔
484
    throw std::invalid_argument("String table index not defined.");
×
485
  }
486

487
  const size_t size = iterator->second.size();
2✔
488
  for (uint32_t idx = 0; idx < size; ++idx) {
12✔
489
    setVariableValueInternal(
10✔
490
        start_variable_index + static_cast<int32_t>(idx), follow_links,
10✔
491
        static_cast<int32_t>(iterator->second.at(idx)));
10✔
492
  }
493
}
2✔
494

495
void VmSession::performSystemCall(
9✔
496
    int8_t major_code, int8_t minor_code, int32_t variable_index, bool follow_links) {
497
  if (major_code == 0) {  // Time and date related functions
9✔
498
    // Get the current UTC time
499
    const auto now_utc = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
9✔
500
    std::tm utc_tm{};
9✔
501
    gmtime_r(&now_utc, &utc_tm);
9✔
502

503
    // Get the current local time
504
    const auto now_local = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
9✔
505
    std::tm local_tm{};
9✔
506
    localtime_r(&now_local, &local_tm);
9✔
507

508
    const int32_t offset_minutes =
9✔
509
        (local_tm.tm_hour - utc_tm.tm_hour) * 60 + (local_tm.tm_min - utc_tm.tm_min);
9✔
510

511
    switch (minor_code) {
9✔
512
    case 0: {  // UTC Timezone (hours)
1✔
513
      // Calculate the timezone offset in minutes
514
      const auto utc_offset_hours =
1✔
515
          static_cast<int32_t>(std::floor(static_cast<double>(offset_minutes) / 60.0));
1✔
516
      setVariableValueInternal(variable_index, follow_links, utc_offset_hours);
1✔
517
    } break;
1✔
518

519
    case 1: {  // UTC Timezone (minutes)
1✔
520
      // Calculate the timezone offset in minutes
521
      const int32_t utc_offset_minutes = offset_minutes % 60;
1✔
522
      setVariableValueInternal(variable_index, follow_links, utc_offset_minutes);
1✔
523
    } break;
1✔
524

525
    case 2: {  // Seconds
1✔
526
      setVariableValueInternal(variable_index, follow_links, utc_tm.tm_sec);
1✔
527
    } break;
1✔
528

529
    case 3: {  // Minutes
1✔
530
      setVariableValueInternal(variable_index, follow_links, utc_tm.tm_min);
1✔
531
    } break;
1✔
532

533
    case 4: {  // Hours
1✔
534
      setVariableValueInternal(variable_index, follow_links, utc_tm.tm_hour);
1✔
535
    } break;
1✔
536

537
    case 5: {  // Day
1✔
538
      setVariableValueInternal(variable_index, follow_links, utc_tm.tm_mday);
1✔
539
    } break;
1✔
540

541
    case 6: {  // Month
1✔
542
      setVariableValueInternal(variable_index, follow_links, utc_tm.tm_mon);
1✔
543
    } break;
1✔
544

545
    case 7: {  // Year
1✔
546
      setVariableValueInternal(variable_index, follow_links, utc_tm.tm_year);
1✔
547
    } break;
1✔
548

549
    case 8: {  // Week
1✔
550
      const int32_t current_year = utc_tm.tm_year + 1900;
1✔
551
      const int32_t current_day = utc_tm.tm_mday;
1✔
552

553
      // Calculate the first day of the current year
554
      std::tm first_day_of_year{};
1✔
555
      first_day_of_year.tm_year = current_year - 1900;
1✔
556
      first_day_of_year.tm_mon = 0;  // January
1✔
557
      first_day_of_year.tm_mday = 1;
1✔
558

559
      const std::time_t first_day_time = std::mktime(&first_day_of_year);
1✔
560
      std::tm first_day_tm{};
1✔
561
      gmtime_r(&first_day_time, &first_day_tm);
1✔
562
      const int32_t first_day_weekday = first_day_tm.tm_wday;
1✔
563

564
      const int32_t current_week = (current_day - 1 + first_day_weekday) / 7 + 1;
1✔
565
      setVariableValueInternal(variable_index, follow_links, current_week);
1✔
566
    } break;
1✔
567

568
    case 9: {  // Day of Week
×
569
      setVariableValueInternal(variable_index, follow_links, utc_tm.tm_wday);
×
570
    } break;
×
571

572
    default:
×
573
      throw std::invalid_argument("Unknown major/minor code combination for system call: "
574
                                  + std::to_string(major_code) + ", " + std::to_string(minor_code));
×
575
    }
576
  } else {
577
    throw std::invalid_argument("Unknown major code for system call: "
578
                                + std::to_string(major_code));
×
579
  }
580
}
9✔
581

582
void VmSession::bitShiftVariable(int32_t variable_index, bool follow_links, int8_t places) {
6✔
583
  const auto value = static_cast<uint32_t>(getVariableValueInternal(variable_index, follow_links));
6✔
584
  const auto shifted_value =
6✔
585
      places > 0 ? value << static_cast<uint32_t>(places) : value >> static_cast<uint32_t>(-places);
6✔
586
  setVariableValueInternal(variable_index, follow_links, static_cast<int32_t>(shifted_value));
6✔
587
}
6✔
588

589
void VmSession::bitWiseInvertVariable(int32_t variable_index, bool follow_links) {
1✔
590
  const auto value = static_cast<uint32_t>(getVariableValueInternal(variable_index, follow_links));
1✔
591
  const auto inverted_value = ~value;
1✔
592
  setVariableValueInternal(variable_index, follow_links, static_cast<int32_t>(inverted_value));
1✔
593
}
1✔
594

595
void VmSession::bitWiseAndTwoVariables(
1✔
596
    int32_t variable_index_a, bool follow_links_a, int32_t variable_index_b, bool follow_links_b) {
597
  const auto value_a =
598
      static_cast<uint32_t>(getVariableValueInternal(variable_index_a, follow_links_a));
1✔
599
  const auto value_b =
600
      static_cast<uint32_t>(getVariableValueInternal(variable_index_b, follow_links_b));
1✔
601
  const uint32_t result = value_a & value_b;
1✔
602
  setVariableValueInternal(variable_index_b, follow_links_b, static_cast<int32_t>(result));
1✔
603
}
1✔
604

605
void VmSession::bitWiseOrTwoVariables(
1✔
606
    int32_t variable_index_a, bool follow_links_a, int32_t variable_index_b, bool follow_links_b) {
607
  const auto value_a =
608
      static_cast<uint32_t>(getVariableValueInternal(variable_index_a, follow_links_a));
1✔
609
  const auto value_b =
610
      static_cast<uint32_t>(getVariableValueInternal(variable_index_b, follow_links_b));
1✔
611
  const uint32_t result = value_a | value_b;
1✔
612
  setVariableValueInternal(variable_index_b, follow_links_b, static_cast<int32_t>(result));
1✔
613
}
1✔
614

615
void VmSession::bitWiseXorTwoVariables(
1✔
616
    int32_t variable_index_a, bool follow_links_a, int32_t variable_index_b, bool follow_links_b) {
617
  const auto value_a =
618
      static_cast<uint32_t>(getVariableValueInternal(variable_index_a, follow_links_a));
1✔
619
  const auto value_b =
620
      static_cast<uint32_t>(getVariableValueInternal(variable_index_b, follow_links_b));
1✔
621
  const uint32_t result = value_a ^ value_b;
1✔
622
  setVariableValueInternal(variable_index_b, follow_links_b, static_cast<int32_t>(result));
1✔
623
}
1✔
624

625
void VmSession::moduloVariableByConstant(
1✔
626
    int32_t variable_index, bool follow_links, int32_t constant) {
627
  const int32_t value = getVariableValueInternal(variable_index, follow_links);
1✔
628
  const int32_t result = value % constant;
1✔
629
  setVariableValueInternal(variable_index, follow_links, result);
1✔
630
}
1✔
631

632
void VmSession::moduloVariableByVariable(
1✔
633
    int32_t variable_index, bool follow_links,
634
    int32_t modulo_variable_index, bool modulo_follow_links) {
635
  const int32_t value = getVariableValueInternal(variable_index, follow_links);
1✔
636
  const int32_t modulo_value = getVariableValueInternal(modulo_variable_index, modulo_follow_links);
1✔
637
  const int32_t result = value % modulo_value;
1✔
638
  setVariableValueInternal(variable_index, follow_links, result);
1✔
639
}
1✔
640

641
void VmSession::rotateVariable(int32_t variable_index, bool follow_links, int8_t places) {
4✔
642
  const auto value = static_cast<uint32_t>(getVariableValueInternal(variable_index, follow_links));
4✔
643
  const auto abs_places = static_cast<uint8_t>(std::abs(places));
4✔
644
  if (places < 0) {
4✔
645
   // Rotate right
646
    const uint32_t result =
2✔
647
        (value >> abs_places) | (value << static_cast<uint32_t>(32 - abs_places));
2✔
648
    setVariableValueInternal(variable_index, follow_links, static_cast<int32_t>(result));
2✔
649
  } else {
650
    // Rotate left
651
    const uint32_t result =
2✔
652
        (value << abs_places) | (value >> static_cast<uint32_t>(32 - abs_places));
2✔
653
    setVariableValueInternal(variable_index, follow_links, static_cast<int32_t>(result));
2✔
654
  }
655
}
4✔
656

657
void VmSession::pushVariableOnStack(
3✔
658
    int32_t stack_variable_index, bool stack_follow_links,
659
    int32_t variable_index, bool follow_links) {
660
  const int32_t current_stack_size =
661
      getVariableValueInternal(stack_variable_index, stack_follow_links);
3✔
662
  const int32_t new_value = getVariableValueInternal(variable_index, follow_links);
3✔
663
  setVariableValueInternal(
3✔
664
    stack_variable_index + 1 + current_stack_size, stack_follow_links, new_value);
3✔
665
  setVariableValueInternal(stack_variable_index, stack_follow_links, current_stack_size + 1);
3✔
666
}
3✔
667

668
void VmSession::pushConstantOnStack(
4✔
669
    int32_t stack_variable_index, bool stack_follow_links, int32_t constant) {
670
  const int32_t current_stack_size =
671
      getVariableValueInternal(stack_variable_index, stack_follow_links);
4✔
672
  setVariableValueInternal(
4✔
673
      stack_variable_index + 1 + current_stack_size, stack_follow_links, constant);
4✔
674
  setVariableValueInternal(stack_variable_index, stack_follow_links, current_stack_size + 1);
4✔
675
}
4✔
676

677
void VmSession::popVariableFromStack(
6✔
678
    int32_t stack_variable_index, bool stack_follow_links,
679
    int32_t variable_index, bool follow_links) {
680
  const int32_t current_stack_size =
681
      getVariableValueInternal(stack_variable_index, stack_follow_links);
6✔
682
  if (current_stack_size == 0) {
6✔
683
    throw std::underflow_error("Cannot pop value from stack, stack empty.");
×
684
  }
685
  const int32_t last_value =
686
      getVariableValueInternal(
12✔
687
          stack_variable_index + 1 + current_stack_size - 1, stack_follow_links);
6✔
688
  setVariableValueInternal(stack_variable_index, true, current_stack_size - 1);
6✔
689
  setVariableValueInternal(variable_index, follow_links, last_value);
6✔
690
}
6✔
691

692
void VmSession::popTopItemFromStack(int32_t stack_variable_index, bool stack_follow_links) {
1✔
693
  const int32_t current_stack_size =
694
      getVariableValueInternal(stack_variable_index, stack_follow_links);
1✔
695
  if (current_stack_size == 0) {
1✔
696
    throw std::underflow_error("Cannot pop value from stack, stack empty.");
×
697
  }
698
  setVariableValueInternal(stack_variable_index, true, current_stack_size - 1);
1✔
699
}
1✔
700

701
void VmSession::checkIfStackIsEmpty(
3✔
702
    int32_t stack_variable_index, bool stack_follow_links,
703
    int32_t variable_index, bool follow_links) {
704
  const int32_t value = getVariableValueInternal(stack_variable_index, stack_follow_links);
3✔
705
  setVariableValueInternal(variable_index, follow_links, value == 0x0 ? 0x1 : 0x0);
3✔
706
}
3✔
707

708
void VmSession::swapVariables(
1✔
709
    int32_t variable_index_a, bool follow_links_a, int32_t variable_index_b, bool follow_links_b) {
710
  const int32_t temp = getVariableValueInternal(variable_index_a, follow_links_a);
1✔
711
  setVariableValueInternal(
1✔
712
      variable_index_a, follow_links_a, getVariableValueInternal(variable_index_b, follow_links_b));
713
  setVariableValueInternal(variable_index_b, follow_links_b, temp);
1✔
714
}
1✔
715

716
void VmSession::setVariableStringTableEntry(
2✔
717
    int32_t variable_index, bool follow_links, std::string_view string_content) {
718
  const int32_t string_table_index = getVariableValueInternal(variable_index, follow_links);
2✔
719
  if (string_table_index < 0 || string_table_index >= string_table_count_) {
2✔
720
    throw std::out_of_range("String table index out of bounds.");
1✔
721
  }
722

723
  if (string_content.size() > max_string_size_) {
1✔
724
    throw std::length_error("String too long.");
×
725
  }
726

727
  string_table_[string_table_index] = string_content;
1✔
728
}
1✔
729

730
void VmSession::printVariableStringFromStringTable(int32_t variable_index, bool follow_links) {
1✔
731
  const int32_t string_table_index = getVariableValueInternal(variable_index, follow_links);
1✔
732
  if (string_table_index < 0 || string_table_index >= string_table_count_) {
1✔
733
    throw std::out_of_range("String table index out of bounds.");
×
734
  }
735

736
  appendToPrintBuffer(getStringTableEntry(string_table_index));
1✔
737
}
1✔
738

739
void VmSession::loadVariableStringItemLengthIntoVariable(
2✔
740
    int32_t string_item_variable_index, bool string_item_follow_links,
741
    int32_t variable_index, bool follow_links) {
742
  const int32_t string_table_index =
743
      getVariableValueInternal(string_item_variable_index, string_item_follow_links);
2✔
744
  if (string_table_index < 0 || string_table_index >= string_table_count_) {
2✔
745
    throw std::out_of_range("String table index out of bounds.");
×
746
  }
747

748
  setVariableValueInternal(
2✔
749
      variable_index, follow_links, static_cast<int32_t>(string_table_[string_table_index].size()));
2✔
750
}
2✔
751

752
void VmSession::loadVariableStringItemIntoVariables(
1✔
753
    int32_t string_item_variable_index, bool string_item_follow_links,
754
    int32_t start_variable_index, bool follow_links) {
755
  const int32_t string_table_index =
756
      getVariableValueInternal(string_item_variable_index, string_item_follow_links);
1✔
757
  if (string_table_index < 0 || string_table_index >= string_table_count_) {
1✔
758
    throw std::out_of_range("String table index out of bounds.");
×
759
  }
760

761
  const auto iterator = string_table_.find(string_table_index);
1✔
762
  if (iterator == string_table_.end()) {
1✔
763
    throw std::invalid_argument("String table index not defined.");
×
764
  }
765

766
  const size_t size = iterator->second.size();
1✔
767
  for (uint32_t idx = 0; idx < size; ++idx) {
6✔
768
    setVariableValueInternal(
5✔
769
        start_variable_index + static_cast<int32_t>(idx), follow_links,
5✔
770
        static_cast<int32_t>(iterator->second.at(idx)));
5✔
771
  }
772
}
1✔
773

774
void VmSession::terminateWithVariableReturnCode(int32_t variable_index, bool follow_links) {
1✔
775
  const auto return_code =
776
      static_cast<int8_t>(getVariableValueInternal(variable_index, follow_links));
1✔
777
  return_code_ = return_code;
1✔
778
  was_terminated_ = true;
1✔
779
}
1✔
780

781
void VmSession::variableBitShiftVariableLeft(
1✔
782
    int32_t variable_index, bool follow_links,
783
    int32_t places_variable_index, bool places_follow_links) {
784
  const auto places =
785
      static_cast<int8_t>(getVariableValueInternal(places_variable_index, places_follow_links));
1✔
786
  bitShiftVariable(variable_index, follow_links, places);
1✔
787
}
1✔
788

789
void VmSession::variableBitShiftVariableRight(
1✔
790
    int32_t variable_index, bool follow_links,
791
    int32_t places_variable_index, bool places_follow_links) {
792
  const auto places =
793
      static_cast<int8_t>(getVariableValueInternal(places_variable_index, places_follow_links));
1✔
794
  bitShiftVariable(variable_index, follow_links, static_cast<int8_t>(-places));
1✔
795
}
1✔
796

797
void VmSession::variableRotateVariableLeft(
1✔
798
    int32_t variable_index, bool follow_links,
799
    int32_t places_variable_index, bool places_follow_links) {
800
  const auto places =
801
      static_cast<int8_t>(getVariableValueInternal(places_variable_index, places_follow_links));
1✔
802
  rotateVariable(variable_index, follow_links, places);
1✔
803
}
1✔
804

805
void VmSession::variableRotateVariableRight(
1✔
806
    int32_t variable_index, bool follow_links,
807
    int32_t places_variable_index, bool places_follow_links) {
808
  const auto places =
809
      static_cast<int8_t>(getVariableValueInternal(places_variable_index, places_follow_links));
1✔
810
  rotateVariable(variable_index, follow_links, static_cast<int8_t>(-places));
1✔
811
}
1✔
812

813
void VmSession::compareIfVariableGtConstant(
2✔
814
    int32_t variable_index, bool follow_links, int32_t constant,
815
    int32_t target_variable_index, bool target_follow_links) {
816
  const int32_t value = getVariableValueInternal(variable_index, follow_links);
2✔
817
  setVariableValueInternal(
2✔
818
      target_variable_index, target_follow_links, value > constant ? 0x1 : 0x0);
819
}
2✔
820

821
void VmSession::compareIfVariableLtConstant(
2✔
822
    int32_t variable_index, bool follow_links, int32_t constant,
823
    int32_t target_variable_index, bool target_follow_links) {
824
  const int32_t value = getVariableValueInternal(variable_index, follow_links);
2✔
825
  setVariableValueInternal(
2✔
826
      target_variable_index, target_follow_links, value < constant ? 0x1 : 0x0);
827
}
2✔
828

829
void VmSession::compareIfVariableEqConstant(
2✔
830
    int32_t variable_index, bool follow_links, int32_t constant,
831
    int32_t target_variable_index, bool target_follow_links) {
832
  const int32_t value = getVariableValueInternal(variable_index, follow_links);
2✔
833
  setVariableValueInternal(
2✔
834
      target_variable_index, target_follow_links, value == constant ? 0x1 : 0x0);
835
}
2✔
836

837
void VmSession::compareIfVariableGtVariable(
2✔
838
    int32_t variable_index_a, bool follow_links_a, int32_t variable_index_b, bool follow_links_b,
839
    int32_t target_variable_index, bool target_follow_links) {
840
  const int32_t value_a = getVariableValueInternal(variable_index_a, follow_links_a);
2✔
841
  const int32_t value_b = getVariableValueInternal(variable_index_b, follow_links_b);
2✔
842
  setVariableValueInternal(
2✔
843
      target_variable_index, target_follow_links, value_a > value_b ? 0x1 : 0x0);
844
}
2✔
845

846
void VmSession::compareIfVariableLtVariable(
2✔
847
    int32_t variable_index_a, bool follow_links_a, int32_t variable_index_b, bool follow_links_b,
848
    int32_t target_variable_index, bool target_follow_links) {
849
  const int32_t value_a = getVariableValueInternal(variable_index_a, follow_links_a);
2✔
850
  const int32_t value_b = getVariableValueInternal(variable_index_b, follow_links_b);
2✔
851
  setVariableValueInternal(
2✔
852
      target_variable_index, target_follow_links, value_a < value_b ? 0x1 : 0x0);
853
}
2✔
854

855
void VmSession::compareIfVariableEqVariable(
2✔
856
    int32_t variable_index_a, bool follow_links_a, int32_t variable_index_b, bool follow_links_b,
857
    int32_t target_variable_index, bool target_follow_links) {
858
  const int32_t value_a = getVariableValueInternal(variable_index_a, follow_links_a);
2✔
859
  const int32_t value_b = getVariableValueInternal(variable_index_b, follow_links_b);
2✔
860
  setVariableValueInternal(
2✔
861
      target_variable_index, target_follow_links, value_a == value_b ? 0x1 : 0x0);
862
}
2✔
863

864
void VmSession::getMaxOfVariableAndConstant(
1✔
865
    int32_t variable_index, bool follow_links, int32_t constant,
866
    int32_t target_variable_index, bool target_follow_links) {
867
  const int32_t value = getVariableValueInternal(variable_index, follow_links);
1✔
868
  setVariableValueInternal(
1✔
869
      target_variable_index, target_follow_links, value > constant ? value : constant);
1✔
870
}
1✔
871

872
void VmSession::getMinOfVariableAndConstant(
1✔
873
    int32_t variable_index, bool follow_links, int32_t constant,
874
    int32_t target_variable_index, bool target_follow_links) {
875
  const int32_t value = getVariableValueInternal(variable_index, follow_links);
1✔
876
  setVariableValueInternal(
1✔
877
      target_variable_index, target_follow_links, value < constant ? value : constant);
1✔
878
}
1✔
879

880
void VmSession::getMaxOfVariableAndVariable(
1✔
881
    int32_t variable_index_a, bool follow_links_a, int32_t variable_index_b, bool follow_links_b,
882
    int32_t target_variable_index, bool target_follow_links) {
883
  const int32_t value_a = getVariableValueInternal(variable_index_a, follow_links_a);
1✔
884
  const int32_t value_b = getVariableValueInternal(variable_index_b, follow_links_b);
1✔
885
  setVariableValueInternal(
1✔
886
      target_variable_index, target_follow_links, value_a > value_b ? value_a : value_b);
887
}
1✔
888

889
void VmSession::getMinOfVariableAndVariable(
1✔
890
    int32_t variable_index_a, bool follow_links_a, int32_t variable_index_b, bool follow_links_b,
891
    int32_t target_variable_index, bool target_follow_links) {
892
  const int32_t value_a = getVariableValueInternal(variable_index_a, follow_links_a);
1✔
893
  const int32_t value_b = getVariableValueInternal(variable_index_b, follow_links_b);
1✔
894
  setVariableValueInternal(
1✔
895
      target_variable_index, target_follow_links, value_a < value_b ? value_a : value_b);
896
}
1✔
897

898
void VmSession::printVariable(int32_t variable_index, bool follow_links, bool as_char) {
5✔
899
  appendVariableToPrintBuffer(variable_index, follow_links, as_char);
5✔
900
}
5✔
901

902
void VmSession::printStringFromStringTable(int32_t string_table_index) {
7✔
903
  appendToPrintBuffer(getStringTableEntry(string_table_index));
7✔
904
}
7✔
905

906
}  // 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

© 2025 Coveralls, Inc