/****************************************************************** Utilities for byte operations (c) 1994, 1995 Innobase Oy Created 5/30/1994 Heikki Tuuri *******************************************************************/ /*********************************************************** Creates a 64-bit dulint out of two ulints. */ UNIV_INLINE dulint ut_dulint_create( /*=============*/ /* out: created dulint */ ulint high, /* in: high-order 32 bits */ ulint low) /* in: low-order 32 bits */ { dulint res; ut_ad(high <= 0xFFFFFFFF); ut_ad(low <= 0xFFFFFFFF); res.high = high; res.low = low; return(res); } /*********************************************************** Gets the high-order 32 bits of a dulint. */ UNIV_INLINE ulint ut_dulint_get_high( /*===============*/ /* out: 32 bits in ulint */ dulint d) /* in: dulint */ { return(d.high); } /*********************************************************** Gets the low-order 32 bits of a dulint. */ UNIV_INLINE ulint ut_dulint_get_low( /*==============*/ /* out: 32 bits in ulint */ dulint d) /* in: dulint */ { return(d.low); } /*********************************************************** Converts a dulint (a struct of 2 ulints) to ib_longlong, which is a 64-bit integer type. */ UNIV_INLINE ib_longlong ut_conv_dulint_to_longlong( /*=======================*/ /* out: value in ib_longlong type */ dulint d) /* in: dulint */ { return((ib_longlong)d.low + (((ib_longlong)d.high) << 32)); } /*********************************************************** Tests if a dulint is zero. */ UNIV_INLINE ibool ut_dulint_is_zero( /*==============*/ /* out: TRUE if zero */ dulint a) /* in: dulint */ { if ((a.low == 0) && (a.high == 0)) { return(TRUE); } return(FALSE); } /*********************************************************** Compares two dulints. */ UNIV_INLINE int ut_dulint_cmp( /*==========*/ /* out: -1 if a < b, 0 if a == b, 1 if a > b */ dulint a, /* in: dulint */ dulint b) /* in: dulint */ { if (a.high > b.high) { return(1); } else if (a.high < b.high) { return(-1); } else if (a.low > b.low) { return(1); } else if (a.low < b.low) { return(-1); } else { return(0); } } /*********************************************************** Calculates the max of two dulints. */ UNIV_INLINE dulint ut_dulint_get_max( /*==============*/ /* out: max(a, b) */ dulint a, /* in: dulint */ dulint b) /* in: dulint */ { if (ut_dulint_cmp(a, b) > 0) { return(a); } return(b); } /*********************************************************** Calculates the min of two dulints. */ UNIV_INLINE dulint ut_dulint_get_min( /*==============*/ /* out: min(a, b) */ dulint a, /* in: dulint */ dulint b) /* in: dulint */ { if (ut_dulint_cmp(a, b) > 0) { return(b); } return(a); } /*********************************************************** Adds a ulint to a dulint. */ UNIV_INLINE dulint ut_dulint_add( /*==========*/ /* out: sum a + b */ dulint a, /* in: dulint */ ulint b) /* in: ulint */ { if (0xFFFFFFFFUL - b >= a.low) { a.low += b; return(a); } a.low = a.low - (0xFFFFFFFFUL - b) - 1; a.high++; return(a); } /*********************************************************** Subtracts a ulint from a dulint. */ UNIV_INLINE dulint ut_dulint_subtract( /*===============*/ /* out: a - b */ dulint a, /* in: dulint */ ulint b) /* in: ulint, b <= a */ { if (a.low >= b) { a.low -= b; return(a); } b -= a.low + 1; a.low = 0xFFFFFFFFUL - b; ut_ad(a.high > 0); a.high--; return(a); } /*********************************************************** Subtracts a dulint from another. NOTE that the difference must be positive and smaller that 4G. */ UNIV_INLINE ulint ut_dulint_minus( /*============*/ /* out: a - b */ dulint a, /* in: dulint; NOTE a must be >= b and at most 2 to power 32 - 1 greater */ dulint b) /* in: dulint */ { ulint diff; if (a.high == b.high) { ut_ad(a.low >= b.low); return(a.low - b.low); } ut_ad(a.high == b.high + 1); diff = (ulint)(0xFFFFFFFFUL - b.low); diff += 1 + a.low; ut_ad(diff > a.low); return(diff); } /************************************************************ Rounds a dulint downward to a multiple of a power of 2. */ UNIV_INLINE dulint ut_dulint_align_down( /*=================*/ /* out: rounded value */ dulint n, /* in: number to be rounded */ ulint align_no) /* in: align by this number which must be a power of 2 */ { ulint low, high; ut_ad(align_no > 0); ut_ad(((align_no - 1) & align_no) == 0); low = ut_dulint_get_low(n); high = ut_dulint_get_high(n); low = low & ~(align_no - 1); return(ut_dulint_create(high, low)); } /************************************************************ Rounds a dulint upward to a multiple of a power of 2. */ UNIV_INLINE dulint ut_dulint_align_up( /*===============*/ /* out: rounded value */ dulint n, /* in: number to be rounded */ ulint align_no) /* in: align by this number which must be a power of 2 */ { return(ut_dulint_align_down(ut_dulint_add(n, align_no - 1), align_no)); } /************************************************************ The following function calculates the value of an integer n rounded to the least product of align_no which is >= n. align_no has to be a power of 2. */ UNIV_INLINE ulint ut_calc_align( /*==========*/ /* out: rounded value */ ulint n, /* in: number to be rounded */ ulint align_no) /* in: align by this number */ { ut_ad(align_no > 0); ut_ad(((align_no - 1) & align_no) == 0); return((n + align_no - 1) & ~(align_no - 1)); } /************************************************************* The following function rounds up a pointer to the nearest aligned address. */ UNIV_INLINE void* ut_align( /*=====*/ /* out: aligned pointer */ void* ptr, /* in: pointer */ ulint align_no) /* in: align by this number */ { ut_ad(align_no > 0); ut_ad(((align_no - 1) & align_no) == 0); ut_ad(ptr); ut_ad(sizeof(void*) == sizeof(ulint)); return((void*)((((ulint)ptr) + align_no - 1) & ~(align_no - 1))); } /************************************************************ The following function calculates the value of an integer n rounded to the biggest product of align_no which is <= n. align_no has to be a power of 2. */ UNIV_INLINE ulint ut_calc_align_down( /*===============*/ /* out: rounded value */ ulint n, /* in: number to be rounded */ ulint align_no) /* in: align by this number */ { ut_ad(align_no > 0); ut_ad(((align_no - 1) & align_no) == 0); return(n & ~(align_no - 1)); } /************************************************************* The following function rounds down a pointer to the nearest aligned address. */ UNIV_INLINE void* ut_align_down( /*==========*/ /* out: aligned pointer */ void* ptr, /* in: pointer */ ulint align_no) /* in: align by this number */ { ut_ad(align_no > 0); ut_ad(((align_no - 1) & align_no) == 0); ut_ad(ptr); ut_ad(sizeof(void*) == sizeof(ulint)); return((void*)((((ulint)ptr)) & ~(align_no - 1))); } /************************************************************* The following function computes the offset of a pointer from the nearest aligned address. */ UNIV_INLINE ulint ut_align_offset( /*============*/ /* out: distance from aligned pointer */ const void* ptr, /* in: pointer */ ulint align_no) /* in: align by this number */ { ut_ad(align_no > 0); ut_ad(((align_no - 1) & align_no) == 0); ut_ad(ptr); ut_ad(sizeof(void*) == sizeof(ulint)); return(((ulint)ptr) & (align_no - 1)); } /********************************************************************* Gets the nth bit of a ulint. */ UNIV_INLINE ibool ut_bit_get_nth( /*===========*/ /* out: TRUE if nth bit is 1; 0th bit is defined to be the least significant */ ulint a, /* in: ulint */ ulint n) /* in: nth bit requested */ { ut_ad(n < 8 * sizeof(ulint)); ut_ad(TRUE == 1); return(1 & (a >> n)); } /********************************************************************* Sets the nth bit of a ulint. */ UNIV_INLINE ulint ut_bit_set_nth( /*===========*/ /* out: the ulint with the bit set as requested */ ulint a, /* in: ulint */ ulint n, /* in: nth bit requested */ ibool val) /* in: value for the bit to set */ { ut_ad(n < 8 * sizeof(ulint)); ut_ad(TRUE == 1); if (val) { return((1 << n) | a); } else { return(~(1 << n) & a); } }