Coverage Report

Created: 2025-11-29 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/proc/self/cwd/common/operators.cc
Line
Count
Source
1
// Copyright 2019 Google LLC
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
#include "common/operators.h"
16
17
#include <string>
18
19
#include "absl/container/flat_hash_map.h"
20
#include "absl/strings/string_view.h"
21
#include "absl/types/optional.h"
22
23
#undef IN
24
25
namespace google::api::expr::common {
26
27
namespace {
28
// These functions provide access to reverse mappings for operators.
29
// Functions generally map from text expression to Expr representation,
30
// e.g., from "&&" to "_&&_". Reverse operators provides a mapping from
31
// Expr to textual mapping, e.g., from "_&&_" to "&&".
32
33
0
const absl::flat_hash_map<std::string, std::string>& UnaryOperators() {
34
0
  static auto* unaries_map = new absl::flat_hash_map<std::string, std::string>{
35
0
      {CelOperator::NEGATE, "-"}, {CelOperator::LOGICAL_NOT, "!"}};
36
0
  return *unaries_map;
37
0
}
38
39
0
const absl::flat_hash_map<std::string, std::string>& BinaryOperators() {
40
0
  static auto* binops_map = new absl::flat_hash_map<std::string, std::string>{
41
0
      {CelOperator::LOGICAL_OR, "||"},
42
0
      {CelOperator::LOGICAL_AND, "&&"},
43
0
      {CelOperator::LESS_EQUALS, "<="},
44
0
      {CelOperator::LESS, "<"},
45
0
      {CelOperator::GREATER_EQUALS, ">="},
46
0
      {CelOperator::GREATER, ">"},
47
0
      {CelOperator::EQUALS, "=="},
48
0
      {CelOperator::NOT_EQUALS, "!="},
49
0
      {CelOperator::IN_DEPRECATED, "in"},
50
0
      {CelOperator::IN, "in"},
51
0
      {CelOperator::ADD, "+"},
52
0
      {CelOperator::SUBTRACT, "-"},
53
0
      {CelOperator::MULTIPLY, "*"},
54
0
      {CelOperator::DIVIDE, "/"},
55
0
      {CelOperator::MODULO, "%"}};
56
0
  return *binops_map;
57
0
}
58
59
734k
const absl::flat_hash_map<std::string, std::string>& ReverseOperators() {
60
734k
  static auto* operators_map =
61
734k
      new absl::flat_hash_map<std::string, std::string>{
62
734k
          {"+", CelOperator::ADD},
63
734k
          {"-", CelOperator::SUBTRACT},
64
734k
          {"*", CelOperator::MULTIPLY},
65
734k
          {"/", CelOperator::DIVIDE},
66
734k
          {"%", CelOperator::MODULO},
67
734k
          {"==", CelOperator::EQUALS},
68
734k
          {"!=", CelOperator::NOT_EQUALS},
69
734k
          {">", CelOperator::GREATER},
70
734k
          {">=", CelOperator::GREATER_EQUALS},
71
734k
          {"<", CelOperator::LESS},
72
734k
          {"<=", CelOperator::LESS_EQUALS},
73
734k
          {"&&", CelOperator::LOGICAL_AND},
74
734k
          {"!", CelOperator::LOGICAL_NOT},
75
734k
          {"||", CelOperator::LOGICAL_OR},
76
734k
          {"in", CelOperator::IN},
77
734k
      };
78
734k
  return *operators_map;
79
734k
}
80
81
0
const absl::flat_hash_map<std::string, std::string>& Operators() {
82
0
  static auto* operators_map =
83
0
      new absl::flat_hash_map<std::string, std::string>{
84
0
          {CelOperator::ADD, "+"},
85
0
          {CelOperator::SUBTRACT, "-"},
86
0
          {CelOperator::MULTIPLY, "*"},
87
0
          {CelOperator::DIVIDE, "/"},
88
0
          {CelOperator::MODULO, "%"},
89
0
          {CelOperator::EQUALS, "=="},
90
0
          {CelOperator::NOT_EQUALS, "!="},
91
0
          {CelOperator::GREATER, ">"},
92
0
          {CelOperator::GREATER_EQUALS, ">="},
93
0
          {CelOperator::LESS, "<"},
94
0
          {CelOperator::LESS_EQUALS, "<="},
95
0
          {CelOperator::LOGICAL_AND, "&&"},
96
0
          {CelOperator::LOGICAL_NOT, "!"},
97
0
          {CelOperator::LOGICAL_OR, "||"},
98
0
          {CelOperator::IN, "in"},
99
0
          {CelOperator::IN_DEPRECATED, "in"},
100
0
          {CelOperator::NEGATE, "-"}};
101
0
  return *operators_map;
102
0
}
103
104
// precedence of the operator, where the higher value means higher.
105
0
const absl::flat_hash_map<std::string, int>& Precedences() {
106
0
  static auto* precedence_map = new absl::flat_hash_map<std::string, int>{
107
0
      {CelOperator::CONDITIONAL, 8},
108
109
0
      {CelOperator::LOGICAL_OR, 7},
110
111
0
      {CelOperator::LOGICAL_AND, 6},
112
113
0
      {CelOperator::EQUALS, 5},
114
0
      {CelOperator::GREATER, 5},
115
0
      {CelOperator::GREATER_EQUALS, 5},
116
0
      {CelOperator::IN, 5},
117
0
      {CelOperator::LESS, 5},
118
0
      {CelOperator::LESS_EQUALS, 5},
119
0
      {CelOperator::NOT_EQUALS, 5},
120
0
      {CelOperator::IN_DEPRECATED, 5},
121
122
0
      {CelOperator::ADD, 4},
123
0
      {CelOperator::SUBTRACT, 4},
124
125
0
      {CelOperator::DIVIDE, 3},
126
0
      {CelOperator::MODULO, 3},
127
0
      {CelOperator::MULTIPLY, 3},
128
129
0
      {CelOperator::LOGICAL_NOT, 2},
130
0
      {CelOperator::NEGATE, 2},
131
132
0
      {CelOperator::INDEX, 1}};
133
0
  return *precedence_map;
134
0
}
135
136
}  // namespace
137
138
const char* CelOperator::CONDITIONAL = "_?_:_";
139
const char* CelOperator::LOGICAL_AND = "_&&_";
140
const char* CelOperator::LOGICAL_OR = "_||_";
141
const char* CelOperator::LOGICAL_NOT = "!_";
142
const char* CelOperator::IN_DEPRECATED = "_in_";
143
const char* CelOperator::EQUALS = "_==_";
144
const char* CelOperator::NOT_EQUALS = "_!=_";
145
const char* CelOperator::LESS = "_<_";
146
const char* CelOperator::LESS_EQUALS = "_<=_";
147
const char* CelOperator::GREATER = "_>_";
148
const char* CelOperator::GREATER_EQUALS = "_>=_";
149
const char* CelOperator::ADD = "_+_";
150
const char* CelOperator::SUBTRACT = "_-_";
151
const char* CelOperator::MULTIPLY = "_*_";
152
const char* CelOperator::DIVIDE = "_/_";
153
const char* CelOperator::MODULO = "_%_";
154
const char* CelOperator::NEGATE = "-_";
155
const char* CelOperator::INDEX = "_[_]";
156
const char* CelOperator::HAS = "has";
157
const char* CelOperator::ALL = "all";
158
const char* CelOperator::EXISTS = "exists";
159
const char* CelOperator::EXISTS_ONE = "exists_one";
160
const char* CelOperator::MAP = "map";
161
const char* CelOperator::FILTER = "filter";
162
const char* CelOperator::NOT_STRICTLY_FALSE = "@not_strictly_false";
163
const char* CelOperator::IN = "@in";
164
165
const absl::string_view CelOperator::OPT_INDEX = "_[?_]";
166
const absl::string_view CelOperator::OPT_SELECT = "_?._";
167
168
0
int LookupPrecedence(const std::string& op) {
169
0
  auto precs = Precedences();
170
0
  auto p = precs.find(op);
171
0
  if (p != precs.end()) {
172
0
    return p->second;
173
0
  }
174
0
  return 0;
175
0
}
176
177
0
absl::optional<std::string> LookupUnaryOperator(const std::string& op) {
178
0
  auto unary_ops = UnaryOperators();
179
0
  auto o = unary_ops.find(op);
180
0
  if (o == unary_ops.end()) {
181
0
    return absl::optional<std::string>();
182
0
  }
183
0
  return o->second;
184
0
}
185
186
0
absl::optional<std::string> LookupBinaryOperator(const std::string& op) {
187
0
  auto bin_ops = BinaryOperators();
188
0
  auto o = bin_ops.find(op);
189
0
  if (o == bin_ops.end()) {
190
0
    return absl::optional<std::string>();
191
0
  }
192
0
  return o->second;
193
0
}
194
195
0
absl::optional<std::string> LookupOperator(const std::string& op) {
196
0
  auto ops = Operators();
197
0
  auto o = ops.find(op);
198
0
  if (o == ops.end()) {
199
0
    return absl::optional<std::string>();
200
0
  }
201
0
  return o->second;
202
0
}
203
204
734k
absl::optional<std::string> ReverseLookupOperator(const std::string& op) {
205
734k
  auto rev_ops = ReverseOperators();
206
734k
  auto o = rev_ops.find(op);
207
734k
  if (o == rev_ops.end()) {
208
0
    return absl::optional<std::string>();
209
0
  }
210
734k
  return o->second;
211
734k
}
212
213
bool IsOperatorSamePrecedence(const std::string& op,
214
0
                              const cel::expr::Expr& expr) {
215
0
  if (!expr.has_call_expr()) {
216
0
    return false;
217
0
  }
218
0
  return LookupPrecedence(op) == LookupPrecedence(expr.call_expr().function());
219
0
}
220
221
bool IsOperatorLowerPrecedence(const std::string& op,
222
0
                               const cel::expr::Expr& expr) {
223
0
  if (!expr.has_call_expr()) {
224
0
    return false;
225
0
  }
226
0
  return LookupPrecedence(op) < LookupPrecedence(expr.call_expr().function());
227
0
}
228
229
0
bool IsOperatorLeftRecursive(const std::string& op) {
230
0
  return op != CelOperator::LOGICAL_AND && op != CelOperator::LOGICAL_OR;
231
0
}
232
233
}  // namespace google::api::expr::common