update to ida 7.6, add builds
This commit is contained in:
350
idasdk76/include/bitrange.hpp
Normal file
350
idasdk76/include/bitrange.hpp
Normal file
@@ -0,0 +1,350 @@
|
||||
#ifndef _BITMASK_HPP
|
||||
#define _BITMASK_HPP
|
||||
|
||||
/*! \file bitrange.hpp
|
||||
|
||||
\brief Definition of the ::bitrange_t class
|
||||
|
||||
*/
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/// This class manages the offset and size of a value that occupies
|
||||
/// a number of contiguous bits within some container - generally a byte array.
|
||||
/// A special state - empty range (both offset and size are zeroes) - determines
|
||||
/// the value as all bits of the container.
|
||||
class bitrange_t
|
||||
{
|
||||
public:
|
||||
/// Constructor
|
||||
explicit bitrange_t(uint16 bit_ofs = 0, uint16 size_in_bits = 0);
|
||||
/// Initialize offset and size to given values
|
||||
inline void init(uint16 bit_ofs, uint16 size_in_bits);
|
||||
|
||||
/// Make the bitrange empty
|
||||
inline void reset();
|
||||
/// Is the bitrange empty?
|
||||
inline bool empty() const;
|
||||
|
||||
/// Get offset of 1st bit
|
||||
inline uint bitoff() const;
|
||||
/// Get size of the value in bits
|
||||
inline uint bitsize() const;
|
||||
/// Size of the value in bytes
|
||||
inline uint bytesize() const;
|
||||
/// Convert to mask of 64 bits
|
||||
inline uint64 mask64() const;
|
||||
|
||||
/// Does have common bits with another bitrange?
|
||||
inline bool has_common(const bitrange_t &r) const;
|
||||
|
||||
/// Apply mask to a bitrange
|
||||
/// \param subrange range *inside* the main bitrange to keep
|
||||
/// After this operation the main bitrange will be truncated
|
||||
/// to have only the bits that are specified by subrange.
|
||||
/// Example: [off=8,nbits=4], subrange[off=1,nbits=2] => [off=9,nbits=2]
|
||||
/// \return success
|
||||
inline bool apply_mask(const bitrange_t &subrange);
|
||||
|
||||
/// Intersect two ranges
|
||||
inline void intersect(const bitrange_t &r);
|
||||
|
||||
/// Create union of 2 ranges including the hole between them
|
||||
inline void create_union(const bitrange_t &r);
|
||||
|
||||
/// Subtract a bitrange
|
||||
inline bool sub(const bitrange_t &r);
|
||||
|
||||
/// Shift range down (left)
|
||||
inline void shift_down(uint cnt);
|
||||
/// Shift range up (right)
|
||||
inline void shift_up(uint cnt);
|
||||
|
||||
/// Initialize bitrange_t with offset/size defined by given mask
|
||||
template <class T> inline void assign_max_nonzero(T mask);
|
||||
|
||||
/// \name Extract
|
||||
/// Extract a value from 'src' according to the bitrange
|
||||
/// \param dst vector the extracted value will be stored to
|
||||
/// \param src source buffer
|
||||
/// \param src_size size of source buffer
|
||||
/// \param is_mf is Msb First? (TRUE-big endian, FALSE-little endian)
|
||||
//@{
|
||||
inline bool extract(
|
||||
bytevec_t *dst,
|
||||
const void *src,
|
||||
size_t src_size,
|
||||
bool is_mf) const;
|
||||
inline bool extract(
|
||||
void *dst,
|
||||
size_t dst_size,
|
||||
const void *src,
|
||||
size_t src_size,
|
||||
bool is_mf) const;
|
||||
//@}
|
||||
|
||||
/// \name Inject
|
||||
/// Inject a value into 'dst' according to the bitrange
|
||||
/// \param dst a buffer the value will be injected into
|
||||
/// \param dst_size size of buffer
|
||||
/// \param src source value
|
||||
/// \param is_mf is Msb First? (TRUE-big endian, FALSE-little endian)
|
||||
//@{
|
||||
inline bool inject(
|
||||
void *dst,
|
||||
size_t dst_size,
|
||||
const void *src,
|
||||
size_t src_size,
|
||||
bool is_mf) const;
|
||||
inline bool inject(
|
||||
void *dst,
|
||||
size_t dst_size,
|
||||
const bytevec_t &src,
|
||||
bool is_mf) const;
|
||||
//@}
|
||||
|
||||
DECLARE_COMPARISONS(bitrange_t);
|
||||
|
||||
private:
|
||||
uint16 offset; ///< offset of 1st bit starting with the lowest bit
|
||||
uint16 nbits; ///< size of the value in bits
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
inline bitrange_t::bitrange_t(uint16 bit_ofs, uint16 size_in_bits)
|
||||
: offset(bit_ofs), nbits(size_in_bits)
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
inline void bitrange_t::init(uint16 bit_ofs, uint16 size_in_bits)
|
||||
{
|
||||
offset = bit_ofs;
|
||||
nbits = size_in_bits;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
inline void bitrange_t::reset()
|
||||
{
|
||||
init(0, 0);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
inline bool bitrange_t::empty() const
|
||||
{
|
||||
return nbits == 0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
inline uint bitrange_t::bitoff() const
|
||||
{
|
||||
return offset;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
inline uint bitrange_t::bitsize() const
|
||||
{
|
||||
return nbits;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
inline uint bitrange_t::bytesize() const
|
||||
{
|
||||
return (nbits + 8-1) / 8;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
inline uint64 bitrange_t::mask64() const
|
||||
{
|
||||
return empty() ? 0 : (left_shift(uint64(1), nbits)-1) << offset;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
inline bool bitrange_t::apply_mask(const bitrange_t &submask)
|
||||
{
|
||||
if ( submask.bitoff() + submask.bitsize() > bitsize() )
|
||||
return false;
|
||||
init(bitoff() + submask.bitoff(), submask.bitsize());
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
inline void bitrange_t::intersect(const bitrange_t &r)
|
||||
{
|
||||
uint16 e1 = offset + nbits;
|
||||
uint16 e2 = r.offset + r.nbits;
|
||||
uint16 e = qmin(e1, e2);
|
||||
uint16 s = qmax(offset, r.offset);
|
||||
if ( s > e )
|
||||
{
|
||||
s = 0;
|
||||
e = 0;
|
||||
}
|
||||
init(s, e-s);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
inline bool bitrange_t::has_common(const bitrange_t &r) const
|
||||
{
|
||||
return interval::overlap(offset, nbits, r.offset, r.nbits);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
inline void bitrange_t::create_union(const bitrange_t &r)
|
||||
{
|
||||
uint16 e1 = offset + nbits;
|
||||
uint16 e2 = r.offset + r.nbits;
|
||||
uint16 e = qmax(e1, e2);
|
||||
uint16 s = qmin(offset, r.offset);
|
||||
init(s, e-s);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
inline bool bitrange_t::sub(const bitrange_t &r)
|
||||
{
|
||||
// r is in the middle of our bitrange, cannot handle this case
|
||||
// because it would require 2 bitranges :/
|
||||
uint16 end = offset + nbits;
|
||||
uint16 rend = r.offset + r.nbits;
|
||||
if ( r.offset > offset && rend < end )
|
||||
return false;
|
||||
if ( r.offset <= offset )
|
||||
{
|
||||
if ( rend > end )
|
||||
{
|
||||
reset();
|
||||
}
|
||||
else if ( rend > offset )
|
||||
{
|
||||
offset = rend;
|
||||
nbits = end - offset;
|
||||
}
|
||||
}
|
||||
else if ( r.offset < end )
|
||||
{
|
||||
nbits = r.offset - offset;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
inline int bitrange_t::compare(const bitrange_t &r) const
|
||||
{
|
||||
if ( offset != r.offset )
|
||||
return offset < r.offset ? -1 : 1;
|
||||
if ( nbits != r.nbits )
|
||||
return nbits < r.nbits ? -1 : 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
inline void bitrange_t::shift_down(uint cnt)
|
||||
{
|
||||
if ( cnt > offset )
|
||||
{
|
||||
cnt -= offset;
|
||||
offset = 0;
|
||||
if ( cnt > nbits )
|
||||
nbits = 0;
|
||||
else
|
||||
nbits -= cnt;
|
||||
}
|
||||
else
|
||||
{
|
||||
offset -= cnt;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
inline void bitrange_t::shift_up(uint cnt)
|
||||
{
|
||||
offset += cnt;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
template <class T> inline void bitrange_t::assign_max_nonzero(T mask)
|
||||
{
|
||||
if ( mask == T(0) )
|
||||
{
|
||||
reset();
|
||||
return;
|
||||
}
|
||||
int i = 0;
|
||||
T bit = T(1);
|
||||
for ( i=0; i < sizeof(T)*8; ++i, bit <<= 1 )
|
||||
if ( (mask & bit) != 0 )
|
||||
break;
|
||||
offset = i;
|
||||
i = sizeof(T)*8 - 1;
|
||||
bit = left_shift(T(1), i);
|
||||
while ( i >= offset )
|
||||
{
|
||||
if ( (mask & bit) != 0 )
|
||||
break;
|
||||
--i;
|
||||
bit >>= 1;
|
||||
}
|
||||
nbits = i - offset + 1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
#ifndef SWIG
|
||||
/// \name Helper functions
|
||||
/// Should not be called directly!
|
||||
//@{
|
||||
idaman bool ida_export bitrange_t_extract_using_bitrange(const bitrange_t *bm, void *dst, size_t dst_size, const void *src, size_t src_size, bool is_mf);
|
||||
idaman bool ida_export bitrange_t_inject_using_bitrange(const bitrange_t *bm, void *dst, size_t dst_size, const void *src, size_t src_size, bool is_mf);
|
||||
//@}
|
||||
#else
|
||||
#endif // SWIG
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
inline bool bitrange_t::extract(
|
||||
void *dst,
|
||||
size_t dst_size,
|
||||
const void *src,
|
||||
size_t src_size,
|
||||
bool is_mf) const
|
||||
{
|
||||
return bitrange_t_extract_using_bitrange(this, dst, dst_size, src, src_size, is_mf);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
inline bool bitrange_t::extract(
|
||||
bytevec_t *dst,
|
||||
const void *src,
|
||||
size_t src_size,
|
||||
bool is_mf) const
|
||||
{
|
||||
size_t dst_size = empty() ? src_size : bytesize();
|
||||
dst->resize(dst_size);
|
||||
return bitrange_t_extract_using_bitrange(this,
|
||||
dst->begin(), dst_size,
|
||||
src, src_size,
|
||||
is_mf);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
inline bool bitrange_t::inject(
|
||||
void *dst,
|
||||
size_t dst_size,
|
||||
const void *src,
|
||||
size_t src_size,
|
||||
bool is_mf) const
|
||||
{
|
||||
return bitrange_t_inject_using_bitrange(this, dst, dst_size, src, src_size, is_mf);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
inline bool bitrange_t::inject(
|
||||
void *dst,
|
||||
size_t dst_size,
|
||||
const bytevec_t &src,
|
||||
bool is_mf) const
|
||||
{
|
||||
return bitrange_t_inject_using_bitrange(this,
|
||||
dst, dst_size,
|
||||
src.begin(), src.size(),
|
||||
is_mf);
|
||||
}
|
||||
|
||||
#endif // define _BITMASK_HPP
|
||||
Reference in New Issue
Block a user