1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7
8 #ifndef GOOGLE_PROTOBUF_GENERATED_ENUM_UTIL_H__
9 #define GOOGLE_PROTOBUF_GENERATED_ENUM_UTIL_H__
10
11 #include <cstddef>
12 #include <cstdint>
13 #include <string>
14 #include <type_traits>
15 #include <vector>
16
17 #include "absl/strings/string_view.h"
18 #include "absl/types/span.h"
19 #include "google/protobuf/explicitly_constructed.h"
20 #include "google/protobuf/message_lite.h"
21
22 // Must be included last.
23 #include "google/protobuf/port_def.inc"
24
25 #ifdef SWIG
26 #error "You cannot SWIG proto headers"
27 #endif
28
29 namespace google {
30 namespace protobuf {
31
32 // This type trait can be used to cause templates to only match proto2 enum
33 // types.
34 template <typename T>
35 struct is_proto_enum : ::std::false_type {};
36
37 namespace internal {
38
39 // The table entry format for storing enum name-to-value mapping used with lite
40 // protos. This struct and the following related functions should only be used
41 // by protobuf generated code.
42 struct EnumEntry {
43 absl::string_view name;
44 int value;
45 };
46
47 // Looks up a numeric enum value given the string name.
48 PROTOBUF_EXPORT bool LookUpEnumValue(const EnumEntry* enums, size_t size,
49 absl::string_view name, int* value);
50
51 // Looks up an enum name given the numeric value.
52 PROTOBUF_EXPORT int LookUpEnumName(const EnumEntry* enums,
53 const int* sorted_indices, size_t size,
54 int value);
55
56 // Initializes the list of enum names in std::string form.
57 PROTOBUF_EXPORT bool InitializeEnumStrings(
58 const EnumEntry* enums, const int* sorted_indices, size_t size,
59 internal::ExplicitlyConstructed<std::string>* enum_strings);
60
61 // The enum validation format is split in 3 parts:
62 // - A dense sequence, with start+length
63 // - A variable size presence bitmap (in increments of 32 bits)
64 // - A variable size sorted int32_t set for everything else.
65 //
66 // The values are as follows:
67 //
68 // 0 - [ sequence start (int16_t) ] | [ sequence size (uint16_t) ] << 16
69 // 1 - [ bitmap size in bits (uint16_t) ] | [ ordered size (uint16_t) ] << 16
70 // x - [ variable length bitmap ]
71 // y - [ variable length of int32_t values ]
72 //
73 // where the bitmap starts right after the end of the sequence.
74 PROTOBUF_EXPORT bool ValidateEnum(int value, const uint32_t* data);
75 PROTOBUF_EXPORT std::vector<uint32_t> GenerateEnumData(
76 absl::Span<const int32_t> values);
77
ValidateEnumInlined(int value,const uint32_t * data)78 inline PROTOBUF_ALWAYS_INLINE bool ValidateEnumInlined(int value,
79 const uint32_t* data) {
80 const int16_t min_seq = static_cast<int16_t>(data[0] & 0xFFFF);
81 const uint16_t length_seq = static_cast<uint16_t>(data[0] >> 16);
82 uint64_t adjusted =
83 static_cast<uint64_t>(static_cast<int64_t>(value)) - min_seq;
84 // Check if the value is within the sequential part.
85 if (PROTOBUF_PREDICT_TRUE(adjusted < length_seq)) {
86 return true;
87 }
88
89 const uint16_t length_bitmap = static_cast<uint16_t>(data[1] & 0xFFFF);
90 adjusted -= length_seq;
91 // Check if the value is within the bitmap.
92 if (PROTOBUF_PREDICT_TRUE(adjusted < length_bitmap)) {
93 return ((data[2 + (adjusted / 32)] >> (adjusted % 32)) & 1) == 1;
94 }
95
96 // Check if the value is on the ordered part.
97 const uint16_t num_ordered = static_cast<uint16_t>(data[1] >> 16);
98 data += 2 + length_bitmap / 32;
99 size_t pos = 0;
100 while (pos < num_ordered) {
101 const int32_t sample = static_cast<int32_t>(data[pos]);
102 if (sample == value) return true;
103 pos = 2 * pos + (sample > value ? 1 : 2);
104 }
105 return false;
106 }
107
108 } // namespace internal
109 } // namespace protobuf
110 } // namespace google
111
112 #include "google/protobuf/port_undef.inc"
113
114 #endif // GOOGLE_PROTOBUF_GENERATED_ENUM_UTIL_H__
115