Google OR-Tools v9.14
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
proto_enum_utils.h
Go to the documentation of this file.
1// Copyright 2010-2025 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14#ifndef OR_TOOLS_BASE_PROTO_ENUM_UTILS_H_
15#define OR_TOOLS_BASE_PROTO_ENUM_UTILS_H_
16
17// Provides utility functions that help with handling Protocol Buffer enums.
18//
19// Examples:
20//
21// A function to easily iterate over all defined values of an enum known at
22// compile-time:
23//
24// for (Proto::Enum e : EnumerateEnumValues<Proto::Enum>()) {
25// ...
26// }
27//
28
29#include <cstddef>
30#include <iterator>
31
32#include "google/protobuf/descriptor.pb.h"
33#include "google/protobuf/repeated_field.h"
35
36using google::protobuf::GetEnumDescriptor;
37using google::protobuf::RepeatedField;
38
39template <typename E>
41
42template <typename E>
44
45template <typename E>
47
48template <typename E>
50
51// Generic Proto enum iterator.
52template <typename E>
54 public:
55 typedef E value_type;
56 typedef std::forward_iterator_tag iterator_category;
57 typedef int difference_type;
58 typedef E* pointer;
59 typedef E& reference;
60
61 ProtoEnumIterator() : current_(0) {}
62
64 : current_(other.current_) {}
65
67 current_ = other.current_;
68 return *this;
69 }
70
72 ProtoEnumIterator other(*this);
73 ++(*this);
74 return other;
75 }
76
78 ++current_;
79 return *this;
80 }
81
82 E operator*() const {
83 return static_cast<E>(GetEnumDescriptor<E>()->value(current_)->number());
84 }
85
86 private:
87 explicit ProtoEnumIterator(int current) : current_(current) {}
88
89 int current_;
90
91 // Only EnumeratedProtoEnumView can instantiate ProtoEnumIterator.
92 friend class EnumeratedProtoEnumView<E>;
93 friend bool operator==
94 <>(const ProtoEnumIterator<E>& a, const ProtoEnumIterator<E>& b);
95 friend bool operator!=
96 <>(const ProtoEnumIterator<E>& a, const ProtoEnumIterator<E>& b);
97};
98
99template <typename E>
101 return a.current_ == b.current_;
102}
103
104template <typename E>
106 return a.current_ != b.current_;
107}
108
109template <typename E>
111 public:
112 typedef E value_type;
114 iterator begin() const { return iterator(0); }
115 iterator end() const {
116 return iterator(GetEnumDescriptor<E>()->value_count());
117 }
118};
119
120// Returns an EnumeratedProtoEnumView that can be iterated over:
121// for (Proto::Enum e : EnumerateEnumValues<Proto::Enum>()) {
122// ...
123// }
124template <typename E>
128
129// Returns a view that allows to iterate directly over the enum values
130// in an enum repeated field, wrapping the repeated field with a type-safe
131// iterator that provides access to the enum values.
132//
133// for (Enum enum :
134// REPEATED_ENUM_ADAPTER(message, repeated_enum_field)) {
135// ...
136// }
137//
138// It provides greater safety than iterating over the enum directly, as the
139// following will fail to type-check:
140//
141// .proto
142// RightEnum enum = 5;
143//
144// client .cc
145// for (WrongEnum e : REPEATED_ENUM_ADAPTER(proto, enum)) { <- Error: Cannot
146// cast from
147// RightEnum to
148// WrongEnum
149// }
150//
151// NOTE: As per http://shortn/_CYfjpruK6N, unrecognized enum values are treated
152// differently between proto2 and proto3.
153//
154// For proto2, they are stripped out from the message when read, so all
155// unrecognized enum values from the wire format will be skipped when iterating
156// over the wrapper (this is the same behavior as iterating over the
157// RepeatedField<int> directly).
158//
159// For proto3, they are left as-is, so unrecognized enum values from the wire
160// format will still be returned when iterating over the wrapper (this is the
161// same behavior as iterating over the RepeatedField<int> directly).
162//
163#define REPEATED_ENUM_ADAPTER(var, field) \
164 google::protobuf::contrib::utils::internal::RepeatedEnumView< \
165 decltype(var.field(0))>(var.field())
166
167// ==== WARNING TO USERS ====
168// Below are internal implementations, not public API, and may change without
169// notice. Do NOT use directly.
170
171namespace internal {
172
173// Implementation for REPEATED_ENUM_ADAPTER. This does not provide type safety
174// thus should be used through REPEATED_ENUM_ADAPTER only. See cr/246914845 for
175// context.
176template <typename E>
178 public:
180#if __cplusplus < 201703L
181 : public std::iterator<std::input_iterator_tag, E>
182#endif
183 {
184 public:
185 using difference_type = ptrdiff_t;
186 using value_type = E;
187#if __cplusplus >= 201703L
188 using iterator_category = std::input_iterator_tag;
189 using pointer = E*;
190 using reference = E&;
191#endif
192 explicit Iterator(RepeatedField<int>::const_iterator ptr) : ptr_(ptr) {}
193 bool operator==(const Iterator& it) const { return ptr_ == it.ptr_; }
194 bool operator!=(const Iterator& it) const { return ptr_ != it.ptr_; }
196 ++ptr_;
197 return *this;
198 }
199 E operator*() const { return static_cast<E>(*ptr_); }
200
201 private:
202 RepeatedField<int>::const_iterator ptr_;
203 };
204
205 explicit RepeatedEnumView(const RepeatedField<int>& repeated_field)
206 : repeated_field_(repeated_field) {}
207
208 Iterator begin() const { return Iterator(repeated_field_.begin()); }
209 Iterator end() const { return Iterator(repeated_field_.end()); }
210
211 private:
212 const RepeatedField<int>& repeated_field_;
213};
214
215} // namespace internal
216
217} // namespace google::protobuf::contrib::utils
218
219#endif // OR_TOOLS_BASE_PROTO_ENUM_UTILS_H_
ProtoEnumIterator & operator=(const ProtoEnumIterator &other)
RepeatedEnumView(const RepeatedField< int > &repeated_field)
EnumeratedProtoEnumView< E > EnumerateEnumValues()
bool operator!=(const ProtoEnumIterator< E > &a, const ProtoEnumIterator< E > &b)
bool operator==(const ProtoEnumIterator< E > &a, const ProtoEnumIterator< E > &b)
if(!yyg->yy_init)
Definition parser.yy.cc:966