Blame source/uds/bits.h

Packit Service 310c69
/*
Packit Service 310c69
 * Copyright (c) 2020 Red Hat, Inc.
Packit Service 310c69
 *
Packit Service 310c69
 * This program is free software; you can redistribute it and/or
Packit Service 310c69
 * modify it under the terms of the GNU General Public License
Packit Service 310c69
 * as published by the Free Software Foundation; either version 2
Packit Service 310c69
 * of the License, or (at your option) any later version.
Packit Service 310c69
 * 
Packit Service 310c69
 * This program is distributed in the hope that it will be useful,
Packit Service 310c69
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 310c69
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 310c69
 * GNU General Public License for more details.
Packit Service 310c69
 * 
Packit Service 310c69
 * You should have received a copy of the GNU General Public License
Packit Service 310c69
 * along with this program; if not, write to the Free Software
Packit Service 310c69
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
Packit Service 310c69
 * 02110-1301, USA. 
Packit Service 310c69
 *
Packit Service 310c69
 * $Id: //eng/uds-releases/jasper/src/uds/bits.h#1 $
Packit Service 310c69
 */
Packit Service 310c69
Packit Service 310c69
#ifndef BITS_H
Packit Service 310c69
#define BITS_H 1
Packit Service 310c69
Packit Service 310c69
#include "compiler.h"
Packit Service 310c69
#include "numeric.h"
Packit Service 310c69
#include "typeDefs.h"
Packit Service 310c69
Packit Service 310c69
/*
Packit Service 310c69
 * These bit stream and bit field utility routines are used for the
Packit Service 310c69
 * non-byte aligned delta indices.
Packit Service 310c69
 *
Packit Service 310c69
 * Bits and bytes are numbered in little endian order.  For example: Within
Packit Service 310c69
 * a byte, bit 0 is the least significant bit (0x1), and bit 7 is the most
Packit Service 310c69
 * significant bit (0x80).  Within a bit stream, bit 7 is the most
Packit Service 310c69
 * signficant bit of byte 0, and bit 8 is the least significant bit of byte
Packit Service 310c69
 * 1.  Within a byte array, a byte's number corresponds to it's index in
Packit Service 310c69
 * the array.
Packit Service 310c69
 *
Packit Service 310c69
 * The implementation assumes that the native machine is little endian, and
Packit Service 310c69
 * that performance is very important.  These assumptions match our current
Packit Service 310c69
 * operating environment.
Packit Service 310c69
 */
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * This is the largest field size supported by getField & setField.  Any
Packit Service 310c69
 * field that is larger is not guaranteed to fit in a single, byte aligned
Packit Service 310c69
 * uint32_t.
Packit Service 310c69
 **/
Packit Service 310c69
enum { MAX_FIELD_BITS = (sizeof(uint32_t) - 1) * CHAR_BIT + 1 };
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * This is the number of guard bytes needed at the end of the memory byte
Packit Service 310c69
 * array when using the bit utilities.  3 bytes are needed when getField &
Packit Service 310c69
 * setField access a field, because they will access some "extra" bytes
Packit Service 310c69
 * past the end of the field.  And 7 bytes are needed when getBigField &
Packit Service 310c69
 * setBigField access a big field, for the same reason.  Note that moveBits
Packit Service 310c69
 * calls getBigField & setBigField.  7 is rewritten to make it clear how it
Packit Service 310c69
 * is derived.
Packit Service 310c69
 **/
Packit Service 310c69
enum { POST_FIELD_GUARD_BYTES = sizeof(uint64_t) - 1 };
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Get a bit field from a bit stream
Packit Service 310c69
 *
Packit Service 310c69
 * @param memory  The base memory byte address
Packit Service 310c69
 * @param offset  The bit offset into the memory for the start of the field
Packit Service 310c69
 * @param size    The number of bits in the field
Packit Service 310c69
 *
Packit Service 310c69
 * @return the bit field
Packit Service 310c69
 **/
Packit Service 310c69
static INLINE unsigned int getField(const byte *memory, uint64_t offset,
Packit Service 310c69
                                    int size)
Packit Service 310c69
{
Packit Service 310c69
  const void *addr = memory + offset / CHAR_BIT;
Packit Service 310c69
  return (getUInt32LE(addr) >> (offset % CHAR_BIT)) & ((1 << size) - 1);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Set a bit field in a bit stream
Packit Service 310c69
 *
Packit Service 310c69
 * @param value   The value to put into the field
Packit Service 310c69
 * @param memory  The base memory byte address
Packit Service 310c69
 * @param offset  The bit offset into the memory for the start of the field
Packit Service 310c69
 * @param size    The number of bits in the field
Packit Service 310c69
 *
Packit Service 310c69
 * @return the bit field
Packit Service 310c69
 **/
Packit Service 310c69
static INLINE void setField(unsigned int value, byte *memory, uint64_t offset,
Packit Service 310c69
                            int size)
Packit Service 310c69
{
Packit Service 310c69
  void *addr = memory + offset / CHAR_BIT;
Packit Service 310c69
  int shift = offset % CHAR_BIT;
Packit Service 310c69
  uint32_t data = getUInt32LE(addr);
Packit Service 310c69
  data &= ~(((1 << size) - 1) << shift);
Packit Service 310c69
  data |= value << shift;
Packit Service 310c69
  storeUInt32LE(addr, data);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Set a bit field in a bit stream to all ones
Packit Service 310c69
 *
Packit Service 310c69
 * @param memory  The base memory byte address
Packit Service 310c69
 * @param offset  The bit offset into the memory for the start of the field
Packit Service 310c69
 * @param size    The number of bits in the field
Packit Service 310c69
 *
Packit Service 310c69
 * @return the bit field
Packit Service 310c69
 **/
Packit Service 310c69
static INLINE void setOne(byte *memory, uint64_t offset, int size)
Packit Service 310c69
{
Packit Service 310c69
  if (size > 0) {
Packit Service 310c69
    byte *addr = memory + offset / CHAR_BIT;
Packit Service 310c69
    int shift = offset % CHAR_BIT;
Packit Service 310c69
    int count = size + shift > CHAR_BIT ? CHAR_BIT - shift : size;
Packit Service 310c69
    *addr++ |= ((1 << count) - 1) << shift;
Packit Service 310c69
    for (size -= count; size > CHAR_BIT; size -= CHAR_BIT) {
Packit Service 310c69
      *addr++ = 0xFF;
Packit Service 310c69
    }
Packit Service 310c69
    if (size) {
Packit Service 310c69
      *addr |= ~(0xFF << size);
Packit Service 310c69
    }
Packit Service 310c69
  }
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Set a bit field in a bit stream to all zeros
Packit Service 310c69
 *
Packit Service 310c69
 * @param memory  The base memory byte address
Packit Service 310c69
 * @param offset  The bit offset into the memory for the start of the field
Packit Service 310c69
 * @param size    The number of bits in the field
Packit Service 310c69
 *
Packit Service 310c69
 * @return the bit field
Packit Service 310c69
 **/
Packit Service 310c69
static INLINE void setZero(byte *memory, uint64_t offset, int size)
Packit Service 310c69
{
Packit Service 310c69
  if (size > 0) {
Packit Service 310c69
    byte *addr = memory + offset / CHAR_BIT;
Packit Service 310c69
    int shift = offset % CHAR_BIT;
Packit Service 310c69
    int count = size + shift > CHAR_BIT ? CHAR_BIT - shift : size;
Packit Service 310c69
    *addr++ &= ~(((1 << count) - 1) << shift);
Packit Service 310c69
    for (size -= count; size > CHAR_BIT; size -= CHAR_BIT) {
Packit Service 310c69
      *addr++ = 0;
Packit Service 310c69
    }
Packit Service 310c69
    if (size) {
Packit Service 310c69
      *addr &= 0xFF << size;
Packit Service 310c69
    }
Packit Service 310c69
  }
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Get a byte stream from a bit stream, reading a whole number of bytes
Packit Service 310c69
 * from an arbitrary bit boundary.
Packit Service 310c69
 *
Packit Service 310c69
 * @param memory       The base memory byte address for the bit stream
Packit Service 310c69
 * @param offset       The bit offset of the start of the bit stream
Packit Service 310c69
 * @param destination  Where to store the bytes
Packit Service 310c69
 * @param size         The number of bytes
Packit Service 310c69
 **/
Packit Service 310c69
void getBytes(const byte *memory, uint64_t offset, byte *destination, int size);
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Store a byte stream into a bit stream, writing a whole number of bytes
Packit Service 310c69
 * to an arbitrary bit boundary.
Packit Service 310c69
 *
Packit Service 310c69
 * @param memory  The base memory byte address for the bit stream
Packit Service 310c69
 * @param offset  The bit offset of the start of the bit stream
Packit Service 310c69
 * @param source  Where to read the bytes
Packit Service 310c69
 * @param size    The number of bytes
Packit Service 310c69
 **/
Packit Service 310c69
void setBytes(byte *memory, uint64_t offset, const byte *source, int size);
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Move bits from one field to another.  When the fields overlap, behave as
Packit Service 310c69
 * if we first move all the bits from the source to a temporary value, and
Packit Service 310c69
 * then move all the bits from the temporary value to the destination.
Packit Service 310c69
 *
Packit Service 310c69
 * @param sMemory         The base source memory byte address
Packit Service 310c69
 * @param source          Bit offset into memory for the source start
Packit Service 310c69
 * @param dMemory         The base destination memory byte address
Packit Service 310c69
 * @param destination     Bit offset into memory for the destination start
Packit Service 310c69
 * @param size            The number of bits in the field
Packit Service 310c69
 **/
Packit Service 310c69
void moveBits(const byte *sMemory, uint64_t source, byte *dMemory,
Packit Service 310c69
              uint64_t destination, int size);
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Compare bits from one field to another, testing for sameness
Packit Service 310c69
 *
Packit Service 310c69
 * @param mem1     The base memory byte address (first field)
Packit Service 310c69
 * @param offset1  Bit offset into the memory for the start (first field)
Packit Service 310c69
 * @param mem2     The base memory byte address (second field)
Packit Service 310c69
 * @param offset2  Bit offset into the memory for the start (second field)
Packit Service 310c69
 * @param size     The number of bits in the field
Packit Service 310c69
 *
Packit Service 310c69
 * @return true if fields are the same, false if different
Packit Service 310c69
 **/
Packit Service 310c69
bool sameBits(const byte *mem1, uint64_t offset1, const byte *mem2,
Packit Service 310c69
              uint64_t offset2, int size)
Packit Service 310c69
  __attribute__((warn_unused_result));
Packit Service 310c69
Packit Service 310c69
#endif /* BITS_H */