-
-
Notifications
You must be signed in to change notification settings - Fork 52
Expand file tree
/
Copy pathScopeView.cpp
More file actions
130 lines (109 loc) · 3.83 KB
/
ScopeView.cpp
File metadata and controls
130 lines (109 loc) · 3.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include <Ark/VM/ScopeView.hpp>
#include <Ark/Constants.hpp>
#include <cassert>
namespace Ark::internal
{
ScopeView::ScopeView(pair_t* storage, const std::size_t start) noexcept :
m_storage(storage), m_start(start), m_size(0), m_min_id(MaxValue16Bits), m_max_id(0)
{}
bool ScopeView::pushBack(uint16_t id, Value&& val) noexcept
{
if (m_start + m_size >= ScopeStackSize) [[unlikely]]
return false;
if (id < m_min_id)
m_min_id = id;
if (id > m_max_id)
m_max_id = id;
m_storage[m_start + m_size] = std::make_pair(id, std::move(val));
++m_size;
return true;
}
bool ScopeView::pushBack(uint16_t id, const Value& val) noexcept
{
if (m_start + m_size >= ScopeStackSize) [[unlikely]]
return false;
if (id < m_min_id)
m_min_id = id;
if (id > m_max_id)
m_max_id = id;
m_storage[m_start + m_size] = std::make_pair(id, val);
++m_size;
return true;
}
void ScopeView::insertFront(const std::vector<pair_t>& values) noexcept
{
const std::size_t offset_by = values.size();
// If there is one day a bug with bad references, this can be caused by this code,
// called when inserting plugins variables in a scope (because we invalidate said
// references by moving them to another slot inside m_storage).
for (std::size_t i = 0; i < m_size; ++i)
{
// This is a weak attempt to prevent / notice the bug before it goes in production,
// if you hit this assertion read the comments carefully!
assert(m_storage[m_start + m_size - i - 1].second.valueType() != ValueType::Reference && "References can not be moved around!");
m_storage[m_start + m_size - i + offset_by - 1] = m_storage[m_start + m_size - i - 1];
}
std::size_t i = 0;
for (const pair_t& pair : values)
{
const uint16_t id = pair.first;
if (id < m_min_id)
m_min_id = id;
if (id > m_max_id)
m_max_id = id;
m_storage[m_start + i] = pair;
++i;
}
m_size += offset_by;
}
bool ScopeView::maybeHas(const uint16_t id) const noexcept
{
return m_min_id <= id && id <= m_max_id;
}
Value* ScopeView::operator[](const uint16_t id_to_look_for) noexcept
{
if (!maybeHas(id_to_look_for))
return nullptr;
for (std::size_t i = m_start; i < m_start + m_size; ++i)
{
auto& [id, value] = m_storage[i];
if (id == id_to_look_for)
return &value;
}
return nullptr;
}
const Value* ScopeView::operator[](const uint16_t id_to_look_for) const noexcept
{
if (!maybeHas(id_to_look_for))
return nullptr;
for (std::size_t i = m_start; i < m_start + m_size; ++i)
{
auto& [id, value] = m_storage[i];
if (id == id_to_look_for)
return &value;
}
return nullptr;
}
uint16_t ScopeView::idFromValue(const Value& val) const noexcept
{
for (std::size_t i = m_start; i < m_start + m_size; ++i)
{
const auto& [id, value] = m_storage[i];
if (value == val)
return id;
}
return MaxValue16Bits;
}
void ScopeView::reset() noexcept
{
m_size = 0;
m_min_id = MaxValue16Bits;
m_max_id = 0;
}
bool operator==(const ScopeView& A, const ScopeView& B) noexcept
{
// if we have two scopes with the same number of elements and starting at the same position,
// they must be identical, as we have a single storage for all scopes
return A.m_size == B.m_size && A.m_start == B.m_start;
}
}