xref: /aosp_15_r20/external/emboss/runtime/cpp/emboss_enum_view.h (revision 99e0aae7469b87d12f0ad23e61142c2d74c1ef70)
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 // View class template for enums.
16 #ifndef EMBOSS_RUNTIME_CPP_EMBOSS_ENUM_VIEW_H_
17 #define EMBOSS_RUNTIME_CPP_EMBOSS_ENUM_VIEW_H_
18 
19 #include <cctype>
20 #include <cstdint>
21 #include <string>
22 #include <utility>
23 
24 #include "runtime/cpp/emboss_defines.h"
25 #include "runtime/cpp/emboss_view_parameters.h"
26 
27 // Forward declarations for optional text processing helpers.
28 namespace emboss {
29 class TextOutputOptions;
30 namespace support {
31 template <class Stream, class View>
32 bool ReadEnumViewFromTextStream(View *view, Stream *stream);
33 template <class Stream, class View>
34 void WriteEnumViewToTextStream(View *view, Stream *stream,
35                                const TextOutputOptions &options);
36 }  // namespace support
37 }  // namespace emboss
38 
39 namespace emboss {
40 namespace support {
41 
42 // EnumView is a view for Enums inside of bitfields.
43 template <class Enum, class Parameters, class BitViewType>
44 class EnumView final {
45  public:
46   using ValueType = typename ::std::remove_cv<Enum>::type;
47   static_assert(
48       Parameters::kBits <= sizeof(ValueType) * 8,
49       "EnumView requires sizeof(ValueType) * 8 >= Parameters::kBits.");
50   template <typename... Args>
EnumView(Args &&...args)51   explicit EnumView(Args &&...args) : buffer_{::std::forward<Args>(args)...} {}
EnumView()52   EnumView() : buffer_() {}
53   EnumView(const EnumView &) = default;
54   EnumView(EnumView &&) = default;
55   EnumView &operator=(const EnumView &) = default;
56   EnumView &operator=(EnumView &&) = default;
57   ~EnumView() = default;
58 
59   // TODO(bolms): Here and in CouldWriteValue(), the static_casts to ValueType
60   // rely on implementation-defined behavior when ValueType is signed.
Read()61   ValueType Read() const {
62     ValueType result = static_cast<ValueType>(buffer_.ReadUInt());
63     EMBOSS_CHECK(Parameters::ValueIsOk(result));
64     return result;
65   }
UncheckedRead()66   ValueType UncheckedRead() const {
67     return static_cast<ValueType>(buffer_.UncheckedReadUInt());
68   }
Write(ValueType value)69   void Write(ValueType value) const {
70     const bool result = TryToWrite(value);
71     (void)result;
72     EMBOSS_CHECK(result);
73   }
TryToWrite(ValueType value)74   bool TryToWrite(ValueType value) const {
75     if (!CouldWriteValue(value)) return false;
76     if (!IsComplete()) return false;
77     buffer_.WriteUInt(static_cast<typename BitViewType::ValueType>(value));
78     return true;
79   }
CouldWriteValue(ValueType value)80   static constexpr bool CouldWriteValue(ValueType value) {
81     // The value can be written if:
82     //
83     // a) it can fit in BitViewType::ValueType (verified by casting to
84     //    BitViewType::ValueType and back, and making sure that the value is
85     //    unchanged)
86     //
87     // and either:
88     //
89     // b1) the field size is large enough to hold all values, or
90     // b2) the value is less than 2**(field size in bits)
91     return value == static_cast<ValueType>(
92                         static_cast<typename BitViewType::ValueType>(value)) &&
93            ((Parameters::kBits ==
94              sizeof(typename BitViewType::ValueType) * 8) ||
95             (static_cast<typename BitViewType::ValueType>(value) <
96              ((static_cast<typename BitViewType::ValueType>(1)
97                << (Parameters::kBits - 1))
98               << 1))) &&
99            Parameters::ValueIsOk(value);
100   }
UncheckedWrite(ValueType value)101   void UncheckedWrite(ValueType value) const {
102     buffer_.UncheckedWriteUInt(
103         static_cast<typename BitViewType::ValueType>(value));
104   }
105 
106   template <typename OtherView>
CopyFrom(const OtherView & other)107   void CopyFrom(const OtherView &other) const {
108     Write(other.Read());
109   }
110   template <typename OtherView>
UncheckedCopyFrom(const OtherView & other)111   void UncheckedCopyFrom(const OtherView &other) const {
112     UncheckedWrite(other.UncheckedRead());
113   }
114   template <typename OtherView>
TryToCopyFrom(const OtherView & other)115   bool TryToCopyFrom(const OtherView &other) const {
116     return other.Ok() && TryToWrite(other.Read());
117   }
118 
119   // All bit patterns in the underlying buffer are valid, so Ok() is always
120   // true if IsComplete() is true.
Ok()121   bool Ok() const {
122     return IsComplete() && Parameters::ValueIsOk(UncheckedRead());
123   }
124   template <class OtherBitViewType>
Equals(const EnumView<Enum,Parameters,OtherBitViewType> & other)125   bool Equals(const EnumView<Enum, Parameters, OtherBitViewType> &other) const {
126     return Read() == other.Read();
127   }
128   template <class OtherBitViewType>
UncheckedEquals(const EnumView<Enum,Parameters,OtherBitViewType> & other)129   bool UncheckedEquals(
130       const EnumView<Enum, Parameters, OtherBitViewType> &other) const {
131     return UncheckedRead() == other.UncheckedRead();
132   }
IsComplete()133   bool IsComplete() const {
134     return buffer_.Ok() && buffer_.SizeInBits() >= Parameters::kBits;
135   }
136 
137   template <class Stream>
UpdateFromTextStream(Stream * stream)138   bool UpdateFromTextStream(Stream *stream) const {
139     return ::emboss::support::ReadEnumViewFromTextStream(this, stream);
140   }
141 
142   template <class Stream>
WriteToTextStream(Stream * stream,const TextOutputOptions & options)143   void WriteToTextStream(Stream *stream,
144                          const TextOutputOptions &options) const {
145     ::emboss::support::WriteEnumViewToTextStream(this, stream, options);
146   }
147 
IsAggregate()148   static constexpr bool IsAggregate() { return false; }
149 
SizeInBits()150   static constexpr int SizeInBits() { return Parameters::kBits; }
151 
152  private:
153   BitViewType buffer_;
154 };
155 
156 }  // namespace support
157 }  // namespace emboss
158 
159 #endif  // EMBOSS_RUNTIME_CPP_EMBOSS_ENUM_VIEW_H_
160