P4C
The P4 Compiler
Loading...
Searching...
No Matches
P4::HalfOpenRange< Unit, Order > Struct Template Reference

#include <bitrange.h>

Public Types

using FromTo = BitRange::FromTo
 
using MinToMax = BitRange::MinToMax
 
using StartLen = BitRange::StartLen
 
using ZeroToMax = BitRange::ZeroToMax
 

Public Member Functions

 HalfOpenRange (FromTo &&fromTo)
 
 HalfOpenRange (int lo, int hi)
 
 HalfOpenRange (MinToMax &&)
 
 HalfOpenRange (StartLen &&startLen)
 
 HalfOpenRange (std::pair< int, int > range)
 
 HalfOpenRange (ZeroToMax &&)
 
HalfOpenRange canonicalize () const
 
bool contains (HalfOpenRange other) const
 
bool contains (int index) const
 
bool empty () const
 
int hiByte () const
 
HalfOpenRange intersectWith (HalfOpenRange a) const
 
HalfOpenRange intersectWith (int l, int h) const
 
bool isHiAligned () const
 
bool isLoAligned () const
 
int loByte () const
 
int nextByte () const
 
bool operator!= (HalfOpenRange other) const
 
HalfOpenRange operator& (HalfOpenRange a) const
 
HalfOpenRange operator&= (HalfOpenRange a)
 
bool operator< (const HalfOpenRange &other) const
 Total ordering, first by lo, then by hi.
 
bool operator== (HalfOpenRange other) const
 
HalfOpenRange operator| (HalfOpenRange a) const
 
HalfOpenRange operator|= (HalfOpenRange a)
 
bool overlaps (HalfOpenRange a) const
 
bool overlaps (int l, int h) const
 
HalfOpenRange< RangeUnit::Bit, Order > resizedToBits (int size) const
 
HalfOpenRange resizedToBytes (int size) const
 
HalfOpenRange< RangeUnit::Bit, Order > shiftedByBits (int offset) const
 
HalfOpenRange< Unit, Order > shiftedByBytes (int offset) const
 
ssize_t size () const
 
void toJSON (JSONGenerator &json) const
 JSON serialization/deserialization.
 
template<Endian DestOrder>
HalfOpenRange< Unit, DestOrder > toOrder (int spaceSize) const
 
template<RangeUnit DestUnit>
HalfOpenRange< DestUnit, Order > toUnit () const
 
HalfOpenRange unionWith (HalfOpenRange a) const
 
HalfOpenRange unionWith (int l, int h) const
 

Static Public Member Functions

static HalfOpenRange fromJSON (JSONLoader &json)
 

Public Attributes

int hi
 
int lo
 

Static Public Attributes

static constexpr Endian order = Order
 
static constexpr RangeUnit unit = Unit
 

Friends

size_t hash_value (const HalfOpenRange &r)
 

Detailed Description

template<RangeUnit Unit, Endian Order>
struct P4::HalfOpenRange< Unit, Order >

A half-open range of bits or bytes - [lo, hi) - specified in terms of a specific endian order. Half-open ranges include lo but do not include hi, so HalfOpenRange(3, 5) contains 3 and 4 but not 5.

Use a half-open range when you want to allow for the possibility that the range may be empty, which may be represented by setting lo and hi to the same value. Using a half-open range may also make some algorithms more natural to express, and it may make working with external code easier since half-open ranges are idiomatic in C++.

Note that there are many ways to represent an empty range - (1, 1) is empty, for example, but so is (2, 2). Many operations on HalfOpenRanges will canonicalize the empty range representation, so don't rely on it - just call empty() to determine if a range is empty.

XXX: Currently, for backwards compatibility, it's possible to construct ranges where lo is greater than hi. We should enforce that ranges are consistent; we'll add the necessary checks after the existing code has been audited.

XXX: We should also add checks to avoid integer overflow.

Member Function Documentation

◆ canonicalize()

template<RangeUnit Unit, Endian Order>
HalfOpenRange P4::HalfOpenRange< Unit, Order >::canonicalize ( ) const
inline
Returns
a canonicalized version of this range. This only has an effect for empty ranges, which will all be mapped to (0, 0).

◆ contains() [1/2]

template<RangeUnit Unit, Endian Order>
bool P4::HalfOpenRange< Unit, Order >::contains ( HalfOpenRange< Unit, Order > other) const
inline
Returns
true if this range includes the provided range - i.e., if this range contains a superset of the provided range's bits.

◆ contains() [2/2]

template<RangeUnit Unit, Endian Order>
bool P4::HalfOpenRange< Unit, Order >::contains ( int index) const
inline
Returns
true if this range includes the provided index.

◆ empty()

template<RangeUnit Unit, Endian Order>
bool P4::HalfOpenRange< Unit, Order >::empty ( ) const
inline
Returns
true if this range is empty - i.e., it contains no elements.

◆ hiByte()

template<RangeUnit Unit, Endian Order>
int P4::HalfOpenRange< Unit, Order >::hiByte ( ) const
inline
Returns
the byte containing the highest-numbered bit in this interval.

◆ intersectWith()

template<RangeUnit Unit, Endian Order>
HalfOpenRange P4::HalfOpenRange< Unit, Order >::intersectWith ( HalfOpenRange< Unit, Order > a) const
inline
Returns
a range which contains all the bits which are included in both this range and the provided range, or an empty range if there are no bits in common.

◆ isHiAligned()

template<RangeUnit Unit, Endian Order>
bool P4::HalfOpenRange< Unit, Order >::isHiAligned ( ) const
inline
Returns
true if the highest-numbered bit in this range is byte-aligned (meaning that this range stops right before the beginning of a new byte).

◆ isLoAligned()

template<RangeUnit Unit, Endian Order>
bool P4::HalfOpenRange< Unit, Order >::isLoAligned ( ) const
inline
Returns
true if the lowest-numbered bit in this range is byte-aligned.

◆ loByte()

template<RangeUnit Unit, Endian Order>
int P4::HalfOpenRange< Unit, Order >::loByte ( ) const
inline
Returns
the byte containing the lowest-numbered bit in this interval.

◆ nextByte()

template<RangeUnit Unit, Endian Order>
int P4::HalfOpenRange< Unit, Order >::nextByte ( ) const
inline
Returns
the next byte that starts after the end of this interval. May result in integer overflow if used with ZeroToMax or MinToMax-sized ranges.

◆ overlaps()

template<RangeUnit Unit, Endian Order>
bool P4::HalfOpenRange< Unit, Order >::overlaps ( HalfOpenRange< Unit, Order > a) const
inline
Returns
true if this range has some bits in common with the provided range. Note that an empty range never overlaps with any other range, so rangeA == rangeB does not imply that rangeA.overlaps(rangeB).

◆ resizedToBits()

template<RangeUnit Unit, Endian Order>
HalfOpenRange< RangeUnit::Bit, Order > P4::HalfOpenRange< Unit, Order >::resizedToBits ( int size) const
inline
Returns
a new range with the same starting index, but expanded or contracted so that it has the provided size in bits. The end result is always in bits.

◆ resizedToBytes()

template<RangeUnit Unit, Endian Order>
HalfOpenRange P4::HalfOpenRange< Unit, Order >::resizedToBytes ( int size) const
inline
Returns
a new range with the same starting index, but expanded or contracted so that it has the provided size in bytes.

◆ shiftedByBits()

template<RangeUnit Unit, Endian Order>
HalfOpenRange< RangeUnit::Bit, Order > P4::HalfOpenRange< Unit, Order >::shiftedByBits ( int offset) const
inline
Returns
a new range with the same size, but shifted towards the high-numbered bits by the provided amount. No rotation or clamping to zero is applied. The result is always in bits.

◆ shiftedByBytes()

template<RangeUnit Unit, Endian Order>
HalfOpenRange< Unit, Order > P4::HalfOpenRange< Unit, Order >::shiftedByBytes ( int offset) const
inline
Returns
a new range with the same size, but shifted towards the high-numbered bytes by the provided amount. No rotation or clamping to zero is applied.

◆ size()

template<RangeUnit Unit, Endian Order>
ssize_t P4::HalfOpenRange< Unit, Order >::size ( ) const
inline
Returns
the number of elements in this range.

◆ toOrder()

template<RangeUnit Unit, Endian Order>
template<Endian DestOrder>
HalfOpenRange< Unit, DestOrder > P4::HalfOpenRange< Unit, Order >::toOrder ( int spaceSize) const
inline

Convert this range to a range with the specified endian order.

Making this conversion requires specifying the size of the larger space that this range is embedded in. That's because the place we start numbering indices from (the origin, in other words) is changing. For example, given a space with 10 elements, a range of 3 indices within that space may be numbered in two ways as follows: Space: [o o o o o o o o o o] Big endian range: --> [2 3 4] Little endian range: [7 6 5] <-----— We couldn't switch between those numberings without knowing that the space has 10 elements.

Note that this operation may result in integer overflow when dealing with very large ranges. It's generally safe for ZeroToMax as long as the space size is not also near INT_MAX. It's never safe for MinToMax.

Template Parameters
DestOrderThe endian order to convert to.
Parameters
spaceSizeThe size of the space this range is embedded in.
Returns
this range, but converted to the specified endian ordering.

◆ toUnit()

template<RangeUnit Unit, Endian Order>
template<RangeUnit DestUnit>
HalfOpenRange< DestUnit, Order > P4::HalfOpenRange< Unit, Order >::toUnit ( ) const
inline

Convert this range to the smallest enclosing range with the specified unit.

Conversion from bytes to bits is exact, but conversion from bits to bytes is lossy and may cause the size of the range to grow if the bits aren't byte-aligned. If that would be problematic, use isLoAligned() and isHiAligned() to check before converting, or just check that converting the result back to bits yields the original range.

This operation will result in integer overflow when dealing with ZeroToMax or MinToMax-sized ranges.

Template Parameters
DestUnitThe unit to convert to.
Returns
this range, but converted to the specified unit.

◆ unionWith()

template<RangeUnit Unit, Endian Order>
HalfOpenRange P4::HalfOpenRange< Unit, Order >::unionWith ( HalfOpenRange< Unit, Order > a) const
inline
Returns
the smallest range that contains all of the bits in both this range and the provided range. Note that because ranges are contiguous, the result may contain bits that are not in either of the original ranges.

Member Data Documentation

◆ hi

template<RangeUnit Unit, Endian Order>
int P4::HalfOpenRange< Unit, Order >::hi

The highest numbered index in the range. For Endian::Network, this is the least significant bit or byte; for Endian::Little, it's the most significant. Because this is a half-open range, the range element this index identifies is not included in the range.

◆ lo

template<RangeUnit Unit, Endian Order>
int P4::HalfOpenRange< Unit, Order >::lo

The lowest numbered index in the range. For Endian::Network, this is the most significant bit or byte; for Endian::Little, it's the least significant.