-
Notifications
You must be signed in to change notification settings - Fork 73
Expand file tree
/
Copy pathevaluator_stack.h
More file actions
148 lines (124 loc) · 4.61 KB
/
Copy pathevaluator_stack.h
File metadata and controls
148 lines (124 loc) · 4.61 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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#ifndef THIRD_PARTY_CEL_CPP_EVAL_EVAL_EVALUATOR_STACK_H_
#define THIRD_PARTY_CEL_CPP_EVAL_EVAL_EVALUATOR_STACK_H_
#include <type_traits>
#include <utility>
#include <vector>
#include "absl/types/span.h"
#include "base/handle.h"
#include "base/value.h"
#include "eval/eval/attribute_trail.h"
#include "eval/internal/interop.h"
namespace google::api::expr::runtime {
// CelValue stack.
// Implementation is based on vector to allow passing parameters from
// stack as Span<>.
class EvaluatorStack {
public:
explicit EvaluatorStack(size_t max_size)
: max_size_(max_size), current_size_(0) {
Reserve(max_size);
}
// Return the current stack size.
size_t size() const { return current_size_; }
// Return the maximum size of the stack.
size_t max_size() const { return max_size_; }
// Returns true if stack is empty.
bool empty() const { return current_size_ == 0; }
// Attributes stack size.
size_t attribute_size() const { return current_size_; }
// Check that stack has enough elements.
bool HasEnough(size_t size) const { return current_size_ >= size; }
// Dumps the entire stack state as is.
void Clear();
// Gets the last size elements of the stack.
// Checking that stack has enough elements is caller's responsibility.
// Please note that calls to Push may invalidate returned Span object.
absl::Span<const cel::Handle<cel::Value>> GetSpan(size_t size) const {
if (!HasEnough(size)) {
ABSL_LOG(ERROR) << "Requested span size (" << size
<< ") exceeds current stack size: " << current_size_;
}
return absl::Span<const cel::Handle<cel::Value>>(
stack_.data() + current_size_ - size, size);
}
// Gets the last size attribute trails of the stack.
// Checking that stack has enough elements is caller's responsibility.
// Please note that calls to Push may invalidate returned Span object.
absl::Span<const AttributeTrail> GetAttributeSpan(size_t size) const {
return absl::Span<const AttributeTrail>(
attribute_stack_.data() + current_size_ - size, size);
}
// Peeks the last element of the stack.
// Checking that stack is not empty is caller's responsibility.
const cel::Handle<cel::Value>& Peek() const {
if (empty()) {
ABSL_LOG(ERROR) << "Peeking on empty EvaluatorStack";
}
return stack_[current_size_ - 1];
}
// Peeks the last element of the attribute stack.
// Checking that stack is not empty is caller's responsibility.
const AttributeTrail& PeekAttribute() const {
if (empty()) {
ABSL_LOG(ERROR) << "Peeking on empty EvaluatorStack";
}
return attribute_stack_[current_size_ - 1];
}
// Clears the last size elements of the stack.
// Checking that stack has enough elements is caller's responsibility.
void Pop(size_t size) {
if (!HasEnough(size)) {
ABSL_LOG(ERROR) << "Trying to pop more elements (" << size
<< ") than the current stack size: " << current_size_;
}
while (size > 0) {
stack_.pop_back();
attribute_stack_.pop_back();
current_size_--;
size--;
}
}
// Put element on the top of the stack.
void Push(cel::Handle<cel::Value> value) {
Push(std::move(value), AttributeTrail());
}
void Push(cel::Handle<cel::Value> value, AttributeTrail attribute) {
if (current_size_ >= max_size()) {
ABSL_LOG(ERROR) << "No room to push more elements on to EvaluatorStack";
}
stack_.push_back(std::move(value));
attribute_stack_.push_back(std::move(attribute));
current_size_++;
}
// Replace element on the top of the stack.
// Checking that stack is not empty is caller's responsibility.
void PopAndPush(cel::Handle<cel::Value> value) {
PopAndPush(std::move(value), AttributeTrail());
}
// Replace element on the top of the stack.
// Checking that stack is not empty is caller's responsibility.
void PopAndPush(cel::Handle<cel::Value> value, AttributeTrail attribute) {
if (empty()) {
ABSL_LOG(ERROR) << "Cannot PopAndPush on empty stack.";
}
stack_[current_size_ - 1] = std::move(value);
attribute_stack_[current_size_ - 1] = std::move(attribute);
}
// Update the max size of the stack and update capacity if needed.
void SetMaxSize(size_t size) {
max_size_ = size;
Reserve(size);
}
private:
// Preallocate stack.
void Reserve(size_t size) {
stack_.reserve(size);
attribute_stack_.reserve(size);
}
std::vector<cel::Handle<cel::Value>> stack_;
std::vector<AttributeTrail> attribute_stack_;
size_t max_size_;
size_t current_size_;
};
} // namespace google::api::expr::runtime
#endif // THIRD_PARTY_CEL_CPP_EVAL_EVAL_EVALUATOR_STACK_H_