//===--- CharUnits.h - Character units for sizes and offsets ----*- C++ -*-===//
 
//
 
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 
// See https://llvm.org/LICENSE.txt for license information.
 
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 
//
 
//===----------------------------------------------------------------------===//
 
//
 
//  This file defines the CharUnits class
 
//
 
//===----------------------------------------------------------------------===//
 
 
 
#ifndef LLVM_CLANG_AST_CHARUNITS_H
 
#define LLVM_CLANG_AST_CHARUNITS_H
 
 
 
#include "llvm/ADT/DenseMapInfo.h"
 
#include "llvm/Support/Alignment.h"
 
#include "llvm/Support/DataTypes.h"
 
#include "llvm/Support/MathExtras.h"
 
 
 
namespace clang {
 
 
 
  /// CharUnits - This is an opaque type for sizes expressed in character units.
 
  /// Instances of this type represent a quantity as a multiple of the size
 
  /// of the standard C type, char, on the target architecture. As an opaque
 
  /// type, CharUnits protects you from accidentally combining operations on
 
  /// quantities in bit units and character units.
 
  ///
 
  /// In both C and C++, an object of type 'char', 'signed char', or 'unsigned
 
  /// char' occupies exactly one byte, so 'character unit' and 'byte' refer to
 
  /// the same quantity of storage. However, we use the term 'character unit'
 
  /// rather than 'byte' to avoid an implication that a character unit is
 
  /// exactly 8 bits.
 
  ///
 
  /// For portability, never assume that a target character is 8 bits wide. Use
 
  /// CharUnit values wherever you calculate sizes, offsets, or alignments
 
  /// in character units.
 
  class CharUnits {
 
    public:
 
      typedef int64_t QuantityType;
 
 
 
    private:
 
      QuantityType Quantity = 0;
 
 
 
      explicit CharUnits(QuantityType C) : Quantity(C) {}
 
 
 
    public:
 
 
 
      /// CharUnits - A default constructor.
 
      CharUnits() = default;
 
 
 
      /// Zero - Construct a CharUnits quantity of zero.
 
      static CharUnits Zero() {
 
        return CharUnits(0);
 
      }
 
 
 
      /// One - Construct a CharUnits quantity of one.
 
      static CharUnits One() {
 
        return CharUnits(1);
 
      }
 
 
 
      /// fromQuantity - Construct a CharUnits quantity from a raw integer type.
 
      static CharUnits fromQuantity(QuantityType Quantity) {
 
        return CharUnits(Quantity);
 
      }
 
 
 
      /// fromQuantity - Construct a CharUnits quantity from an llvm::Align
 
      /// quantity.
 
      static CharUnits fromQuantity(llvm::Align Quantity) {
 
        return CharUnits(Quantity.value());
 
      }
 
 
 
      // Compound assignment.
 
      CharUnits& operator+= (const CharUnits &Other) {
 
        Quantity += Other.Quantity;
 
        return *this;
 
      }
 
      CharUnits& operator++ () {
 
        ++Quantity;
 
        return *this;
 
      }
 
      CharUnits operator++ (int) {
 
        return CharUnits(Quantity++);
 
      }
 
      CharUnits& operator-= (const CharUnits &Other) {
 
        Quantity -= Other.Quantity;
 
        return *this;
 
      }
 
      CharUnits& operator-- () {
 
        --Quantity;
 
        return *this;
 
      }
 
      CharUnits operator-- (int) {
 
        return CharUnits(Quantity--);
 
      }
 
 
 
      // Comparison operators.
 
      bool operator== (const CharUnits &Other) const {
 
        return Quantity == Other.Quantity;
 
      }
 
      bool operator!= (const CharUnits &Other) const {
 
        return Quantity != Other.Quantity;
 
      }
 
 
 
      // Relational operators.
 
      bool operator<  (const CharUnits &Other) const {
 
        return Quantity <  Other.Quantity;
 
      }
 
      bool operator<= (const CharUnits &Other) const {
 
        return Quantity <= Other.Quantity;
 
      }
 
      bool operator>  (const CharUnits &Other) const {
 
        return Quantity >  Other.Quantity;
 
      }
 
      bool operator>= (const CharUnits &Other) const {
 
        return Quantity >= Other.Quantity;
 
      }
 
 
 
      // Other predicates.
 
 
 
      /// isZero - Test whether the quantity equals zero.
 
      bool isZero() const     { return Quantity == 0; }
 
 
 
      /// isOne - Test whether the quantity equals one.
 
      bool isOne() const      { return Quantity == 1; }
 
 
 
      /// isPositive - Test whether the quantity is greater than zero.
 
      bool isPositive() const { return Quantity  > 0; }
 
 
 
      /// isNegative - Test whether the quantity is less than zero.
 
      bool isNegative() const { return Quantity  < 0; }
 
 
 
      /// isPowerOfTwo - Test whether the quantity is a power of two.
 
      /// Zero is not a power of two.
 
      bool isPowerOfTwo() const {
 
        return (Quantity & -Quantity) == Quantity;
 
      }
 
 
 
      /// Test whether this is a multiple of the other value.
 
      ///
 
      /// Among other things, this promises that
 
      /// self.alignTo(N) will just return self.
 
      bool isMultipleOf(CharUnits N) const {
 
        return (*this % N) == 0;
 
      }
 
 
 
      // Arithmetic operators.
 
      CharUnits operator* (QuantityType N) const {
 
        return CharUnits(Quantity * N);
 
      }
 
      CharUnits &operator*= (QuantityType N) {
 
        Quantity *= N;
 
        return *this;
 
      }
 
      CharUnits operator/ (QuantityType N) const {
 
        return CharUnits(Quantity / N);
 
      }
 
      CharUnits &operator/= (QuantityType N) {
 
        Quantity /= N;
 
        return *this;
 
      }
 
      QuantityType operator/ (const CharUnits &Other) const {
 
        return Quantity / Other.Quantity;
 
      }
 
      CharUnits operator% (QuantityType N) const {
 
        return CharUnits(Quantity % N);
 
      }
 
      QuantityType operator% (const CharUnits &Other) const {
 
        return Quantity % Other.Quantity;
 
      }
 
      CharUnits operator+ (const CharUnits &Other) const {
 
        return CharUnits(Quantity + Other.Quantity);
 
      }
 
      CharUnits operator- (const CharUnits &Other) const {
 
        return CharUnits(Quantity - Other.Quantity);
 
      }
 
      CharUnits operator- () const {
 
        return CharUnits(-Quantity);
 
      }
 
 
 
 
 
      // Conversions.
 
 
 
      /// getQuantity - Get the raw integer representation of this quantity.
 
      QuantityType getQuantity() const { return Quantity; }
 
 
 
      /// getAsAlign - Returns Quantity as a valid llvm::Align,
 
      /// Beware llvm::Align assumes power of two 8-bit bytes.
 
      llvm::Align getAsAlign() const { return llvm::Align(Quantity); }
 
 
 
      /// getAsMaybeAlign - Returns Quantity as a valid llvm::Align or
 
      /// std::nullopt, Beware llvm::MaybeAlign assumes power of two 8-bit
 
      /// bytes.
 
      llvm::MaybeAlign getAsMaybeAlign() const {
 
        return llvm::MaybeAlign(Quantity);
 
      }
 
 
 
      /// alignTo - Returns the next integer (mod 2**64) that is
 
      /// greater than or equal to this quantity and is a multiple of \p Align.
 
      /// Align must be non-zero.
 
      CharUnits alignTo(const CharUnits &Align) const {
 
        return CharUnits(llvm::alignTo(Quantity, Align.Quantity));
 
      }
 
 
 
      /// Given that this is a non-zero alignment value, what is the
 
      /// alignment at the given offset?
 
      CharUnits alignmentAtOffset(CharUnits offset) const {
 
        assert(Quantity != 0 && "offsetting from unknown alignment?");
 
        return CharUnits(llvm::MinAlign(Quantity, offset.Quantity));
 
      }
 
 
 
      /// Given that this is the alignment of the first element of an
 
      /// array, return the minimum alignment of any element in the array.
 
      CharUnits alignmentOfArrayElement(CharUnits elementSize) const {
 
        // Since we don't track offsetted alignments, the alignment of
 
        // the second element (or any odd element) will be minimally
 
        // aligned.
 
        return alignmentAtOffset(elementSize);
 
      }
 
 
 
 
 
  }; // class CharUnit
 
} // namespace clang
 
 
 
inline clang::CharUnits operator* (clang::CharUnits::QuantityType Scale,
 
                                   const clang::CharUnits &CU) {
 
  return CU * Scale;
 
}
 
 
 
namespace llvm {
 
 
 
template<> struct DenseMapInfo<clang::CharUnits> {
 
  static clang::CharUnits getEmptyKey() {
 
    clang::CharUnits::QuantityType Quantity =
 
      DenseMapInfo<clang::CharUnits::QuantityType>::getEmptyKey();
 
 
 
    return clang::CharUnits::fromQuantity(Quantity);
 
  }
 
 
 
  static clang::CharUnits getTombstoneKey() {
 
    clang::CharUnits::QuantityType Quantity =
 
      DenseMapInfo<clang::CharUnits::QuantityType>::getTombstoneKey();
 
 
 
    return clang::CharUnits::fromQuantity(Quantity);
 
  }
 
 
 
  static unsigned getHashValue(const clang::CharUnits &CU) {
 
    clang::CharUnits::QuantityType Quantity = CU.getQuantity();
 
    return DenseMapInfo<clang::CharUnits::QuantityType>::getHashValue(Quantity);
 
  }
 
 
 
  static bool isEqual(const clang::CharUnits &LHS,
 
                      const clang::CharUnits &RHS) {
 
    return LHS == RHS;
 
  }
 
};
 
 
 
} // end namespace llvm
 
 
 
#endif // LLVM_CLANG_AST_CHARUNITS_H