// Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd #ifndef GOOGLE_PROTOBUF_HAS_BITS_H__ #define GOOGLE_PROTOBUF_HAS_BITS_H__ #include #include "google/protobuf/stubs/common.h" #include "google/protobuf/port.h" // Must be included last. #include "google/protobuf/port_def.inc" #ifdef SWIG #error "You cannot SWIG proto headers" #endif namespace google { namespace protobuf { namespace internal { template class HasBits { public: PROTOBUF_NDEBUG_INLINE constexpr HasBits() : has_bits_{} {} constexpr HasBits(std::initializer_list has_bits) : has_bits_{} { Copy(has_bits_, &*has_bits.begin(), has_bits.size()); } PROTOBUF_NDEBUG_INLINE void Clear() { memset(has_bits_, 0, sizeof(has_bits_)); } PROTOBUF_NDEBUG_INLINE uint32_t& operator[](int index) { return has_bits_[index]; } PROTOBUF_NDEBUG_INLINE const uint32_t& operator[](int index) const { return has_bits_[index]; } bool operator==(const HasBits& rhs) const { return memcmp(has_bits_, rhs.has_bits_, sizeof(has_bits_)) == 0; } bool operator!=(const HasBits& rhs) const { return !(*this == rhs); } void Or(const HasBits& rhs) { for (int i = 0; i < doublewords; i++) has_bits_[i] |= rhs.has_bits_[i]; } bool empty() const; private: // Unfortunately, older GCC compilers (and perhaps others) fail on initializer // arguments for an std::array<> or any type of array constructor. Below is a // handrolled constexpr 'Copy' function that we use to make a constexpr // constructor that accepts a `std::initializer` list. static inline constexpr void Copy(uint32_t* dst, const uint32_t* src, size_t n) { assert(n <= doublewords); for (size_t ix = 0; ix < n; ++ix) { dst[ix] = src[ix]; } for (size_t ix = n; ix < doublewords; ++ix) { dst[ix] = 0; } } uint32_t has_bits_[doublewords]; }; template <> inline bool HasBits<1>::empty() const { return !has_bits_[0]; } template <> inline bool HasBits<2>::empty() const { return !(has_bits_[0] | has_bits_[1]); } template <> inline bool HasBits<3>::empty() const { return !(has_bits_[0] | has_bits_[1] | has_bits_[2]); } template <> inline bool HasBits<4>::empty() const { return !(has_bits_[0] | has_bits_[1] | has_bits_[2] | has_bits_[3]); } template inline bool HasBits::empty() const { for (uint32_t bits : has_bits_) { if (bits) return false; } return true; } } // namespace internal } // namespace protobuf } // namespace google #include "google/protobuf/port_undef.inc" #endif // GOOGLE_PROTOBUF_HAS_BITS_H__