Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  bit_struct.h

  Sprache: C
 

/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


#ifndef ART_LIBARTBASE_BASE_BIT_STRUCT_H_
#define ART_LIBARTBASE_BASE_BIT_STRUCT_H_

#include <type_traits>

#include "base/casts.h"
#include "bit_struct_detail.h"
#include "bit_utils.h"

//
// Zero-cost, type-safe, well-defined "structs" of bit fields.
//
// ---------------------------------------------
// Usage example:
// ---------------------------------------------
//
//   // Definition for type 'Example'
//   BITSTRUCT_DEFINE_START(Example, 10)
//     BITSTRUCT_UINT(0, 2) u2;     // Every field must be a BitStruct[*] with the same StorageType,
//     BITSTRUCT_INT(2, 7)  i7;     // preferably using BITSTRUCT_{FIELD,UINT,INT}
//     BITSTRUCT_UINT(9, 1) i1;     // to fill in the StorageType parameter.
//   BITSTRUCT_DEFINE_END(Example);
//
//  Would define a bit struct with this layout:
//   <- 1 ->    <--  7  -->  <- 2 ->
//  +--------+---------------+-----+
//  |   i1   |       i7      | u2  +
//  +--------+---------------+-----+
//  10       9               2     0
//
//   // Read-write just like regular values.
//   Example ex;
//   ex.u2 = 3;
//   ex.i7 = -25;
//   ex.i1 = true;
//   size_t u2 = ex.u2;
//   int i7 = ex.i7;
//   bool i1 = ex.i1;
//
//   // It's packed down to the smallest # of machine words.
//   assert(sizeof(Example) == 2);
//   // The exact bit pattern is well-defined by the template parameters.
//   uint16_t cast = *reinterpret_cast<uint16_t*>(ex);
//   assert(cast == ((3) | (0b100111 << 2) | (true << 9);
//
// ---------------------------------------------
// Why not just use C++ bitfields?
// ---------------------------------------------
//
// The layout is implementation-defined.
// We do not know whether the fields are packed left-to-right or
// right-to-left, so it makes it useless when the memory layout needs to be
// precisely controlled.
//
// ---------------------------------------------
// More info:
// ---------------------------------------------
// Currently uintmax_t is the largest supported underlying storage type,
// all (kBitOffset + kBitWidth) must fit into BitSizeOf<uintmax_t>();
//
// Using BitStruct[U]int will automatically select an underlying type
// that's the smallest to fit your (offset + bitwidth).
//
// BitStructNumber can be used to manually select an underlying type.
//
// BitStructField can be used with custom standard-layout structs,
// thus allowing for arbitrary nesting of bit structs.
//
namespace art {
// Zero-cost wrapper around a struct 'T', allowing it to be stored as a bitfield
// at offset 'kBitOffset' and width 'kBitWidth'.
// The storage is plain unsigned int, whose size is the smallest required  to fit
// 'kBitOffset + kBitWidth'. All operations to this become BitFieldExtract/BitFieldInsert
// operations to the underlying uint.
//
// Field memory representation:
//
// MSB      <-- width  -->      LSB
// +--------+------------+--------+
// | ?????? | u bitfield | ?????? +
// +--------+------------+--------+
//                       offset   0
//
// Reading/writing the bitfield (un)packs it into a temporary T:
//
// MSB               <-- width  --> LSB
// +-----------------+------------+
// | 0.............0 | T bitfield |
// +-----------------+------------+
//                                0
//
// It's the responsibility of the StorageType to ensure the bit representation
// of T can be represented by kBitWidth.
template <typename T,
          size_t kBitOffset,
          size_t kBitWidth,
          typename StorageType>
struct BitStructField {
  static_assert(std::is_standard_layout_v<T>, "T must be standard layout");

  operator T() const {
    return Get();
  }

  // Exclude overload when T==StorageType.
  template <typename _ = void,
            typename = std::enable_if_t<std::is_same_v<T, StorageType>, _>>
  explicit operator StorageType() const {
    return BitFieldExtract(storage_, kBitOffset, kBitWidth);
  }

  BitStructField& operator=(T value) {
    return Assign(*this, value);
  }

  static constexpr size_t BitStructSizeOf() {
    return kBitWidth;
  }

  BitStructField& operator=(const BitStructField& other) {
    // Warning. The default operator= will overwrite the entire storage!
    return *this = static_cast<T>(other);
  }

  BitStructField(const BitStructField& other) {
    Assign(*thisstatic_cast<T>(other));
  }

  BitStructField() = default;
  ~BitStructField() = default;

 protected:
  template <typename T2>
  T2& Assign(T2& what, T value) {
    // Since C++ doesn't allow the type of operator= to change out
    // in the subclass, reimplement operator= in each subclass
    // manually and call this helper function.
    static_assert(std::is_base_of_v<BitStructField, T2>, "T2 must inherit BitStructField");
    what.Set(value);
    return what;
  }

  T Get() const {
    ExtractionType storage = static_cast<ExtractionType>(storage_);
    ExtractionType extracted = BitFieldExtract(storage, kBitOffset, kBitWidth);
    ConversionType to_convert = dchecked_integral_cast<ConversionType>(extracted);
    return ValueConverter::FromUnderlyingStorage(to_convert);
  }

  void Set(T value) {
    ConversionType converted = ValueConverter::ToUnderlyingStorage(value);
    ExtractionType extracted = dchecked_integral_cast<ExtractionType>(converted);
    storage_ = BitFieldInsert(storage_, extracted, kBitOffset, kBitWidth);
  }

 private:
  using ValueConverter = detail::ValueConverter<T>;
  using ConversionType = typename ValueConverter::StorageType;
  using ExtractionType = std::conditional_t<std::is_signed_v<ConversionType>,
                                            std::make_signed_t<StorageType>,
                                            StorageType>;

  StorageType storage_;
};

// Base class for number-like BitStruct fields.
// T is the type to store in as a bit field.
// kBitOffset, kBitWidth define the position and length of the bitfield.
//
// (Common usage should be BitStructInt, BitStructUint -- this
// intermediate template allows a user-defined integer to be used.)
template <typename T, size_t kBitOffset, size_t kBitWidth, typename StorageType>
struct BitStructNumber : public BitStructField<T, kBitOffset, kBitWidth, StorageType> {
  BitStructNumber& operator=(T value) {
    return BaseType::Assign(*this, value);
  }

  /*implicit*/ operator T() const {
    return Get();
  }

  explicit operator bool() const {
    return static_cast<bool>(Get());
  }

  BitStructNumber& operator++() {
    *this = Get() + 1u;
    return *this;
  }

  StorageType operator++(int) {
    return Get() + 1u;
  }

  BitStructNumber& operator--() {
    *this = Get() - 1u;
    return *this;
  }

  StorageType operator--(int) {
    return Get() - 1u;
  }

 private:
  using BaseType = BitStructField<T, kBitOffset, kBitWidth, StorageType>;
  using BaseType::Get;
};

// Create a BitStruct field which uses the smallest underlying int storage type,
// in order to be large enough to fit (kBitOffset + kBitWidth).
//
// Values are sign-extended when they are read out.
template <size_t kBitOffset, size_t kBitWidth, typename StorageType>
using BitStructInt =
    BitStructNumber<typename detail::MinimumTypeHelper<int, kBitOffset + kBitWidth>::type,
                    kBitOffset,
                    kBitWidth,
                    StorageType>;

// Create a BitStruct field which uses the smallest underlying uint storage type,
// in order to be large enough to fit (kBitOffset + kBitWidth).
//
// Values are zero-extended when they are read out.
template <size_t kBitOffset, size_t kBitWidth, typename StorageType>
using BitStructUint =
    BitStructNumber<typename detail::MinimumTypeHelper<unsigned int, kBitOffset + kBitWidth>::type,
                    kBitOffset,
                    kBitWidth,
                    StorageType>;

// Start a definition for a bitstruct.
// A bitstruct is defined to be a union with a common initial subsequence
// that we call 'DefineBitStructSize<bitwidth>'.
//
// See top of file for usage example.
//
// This marker is required by the C++ standard in order to
// have a "common initial sequence".
//
// See C++ 9.5.1 [class.union]:
// If a standard-layout union contains several standard-layout structs that share a common
// initial sequence ... it is permitted to inspect the common initial sequence of any of
// standard-layout struct members.
#define BITSTRUCT_DEFINE_START(name, bitwidth)                                        \
    union name {                                                         /* NOLINT */ \
      using StorageType =                                                             \
          typename detail::MinimumTypeUnsignedHelper<(bitwidth)>::type;               \
      art::detail::DefineBitStructSize<(bitwidth)> _;                                 \
      static constexpr size_t BitStructSizeOf() { return (bitwidth); }                \
      name& operator=(const name& other) { _ = other._; return *this; }  /* NOLINT */ \
      name(const name& other) : _(other._) {}                                         \
      name() = default;                                                               \
      ~name() = default;

// Define a field. See top of file for usage example.
#define BITSTRUCT_FIELD(type, bit_offset, bit_width)                           \
    BitStructField<type, (bit_offset), (bit_width), StorageType>
#define BITSTRUCT_INT(bit_offset, bit_width)                                   \
    BitStructInt<(bit_offset), (bit_width), StorageType>
#define BITSTRUCT_UINT(bit_offset, bit_width)                                  \
    BitStructUint<(bit_offset), (bit_width), StorageType>

// End the definition of a bitstruct, and insert a check
// to ensure that the bitstruct did not exceed the specified size.
//
// See top of file for usage example.
#define BITSTRUCT_DEFINE_END(name)                                             \
    };                                                                         \
    static_assert(art::detail::ValidateBitStructSize<name>(),                  \
                  #name "bitsize incorrect: "                                  \
                  "did you insert extra fields that weren't BitStructX, "      \
                  "and does the size match the sum of the field widths?")

// Determine the minimal bit size for a user-defined type T.
// Used by BitStructField to determine how small a custom type is.
template <typename T>
static constexpr size_t BitStructSizeOf() {
  return T::BitStructSizeOf();
}

}  // namespace art

#endif  // ART_LIBARTBASE_BASE_BIT_STRUCT_H_

Messung V0.5 in Prozent
C=92 H=95 G=93

¤ Dauer der Verarbeitung: 0.10 Sekunden  (vorverarbeitet am  2026-06-29) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik