diff options
Diffstat (limited to 'storage/xtradb/include/mach0data.ic')
-rw-r--r-- | storage/xtradb/include/mach0data.ic | 784 |
1 files changed, 784 insertions, 0 deletions
diff --git a/storage/xtradb/include/mach0data.ic b/storage/xtradb/include/mach0data.ic new file mode 100644 index 00000000000..5dda9aece2f --- /dev/null +++ b/storage/xtradb/include/mach0data.ic @@ -0,0 +1,784 @@ +/***************************************************************************** + +Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved. + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA + +*****************************************************************************/ + +/********************************************************************** +Utilities for converting data from the database file +to the machine format. + +Created 11/28/1995 Heikki Tuuri +***********************************************************************/ + +#include "ut0mem.h" + +/*********************************************************** +The following function is used to store data in one byte. */ +UNIV_INLINE +void +mach_write_to_1( +/*============*/ + byte* b, /* in: pointer to byte where to store */ + ulint n) /* in: ulint integer to be stored, >= 0, < 256 */ +{ + ut_ad(b); + ut_ad(n <= 0xFFUL); + + b[0] = (byte)n; +} + +/************************************************************ +The following function is used to fetch data from one byte. */ +UNIV_INLINE +ulint +mach_read_from_1( +/*=============*/ + /* out: ulint integer, >= 0, < 256 */ + const byte* b) /* in: pointer to byte */ +{ + ut_ad(b); + return((ulint)(b[0])); +} + +/*********************************************************** +The following function is used to store data in two consecutive +bytes. We store the most significant byte to the lowest address. */ +UNIV_INLINE +void +mach_write_to_2( +/*============*/ + byte* b, /* in: pointer to two bytes where to store */ + ulint n) /* in: ulint integer to be stored */ +{ + ut_ad(b); + ut_ad(n <= 0xFFFFUL); + + b[0] = (byte)(n >> 8); + b[1] = (byte)(n); +} + +/************************************************************ +The following function is used to fetch data from 2 consecutive +bytes. The most significant byte is at the lowest address. */ +UNIV_INLINE +ulint +mach_read_from_2( +/*=============*/ + /* out: ulint integer */ + const byte* b) /* in: pointer to 2 bytes */ +{ + ut_ad(b); + return( ((ulint)(b[0]) << 8) + + (ulint)(b[1]) + ); +} + +/************************************************************ +The following function is used to convert a 16-bit data item +to the canonical format, for fast bytewise equality test +against memory. */ +UNIV_INLINE +uint16 +mach_encode_2( +/*==========*/ + /* out: 16-bit integer in canonical format */ + ulint n) /* in: integer in machine-dependent format */ +{ + uint16 ret; + ut_ad(2 == sizeof ret); + mach_write_to_2((byte*) &ret, n); + return(ret); +} +/************************************************************ +The following function is used to convert a 16-bit data item +from the canonical format, for fast bytewise equality test +against memory. */ +UNIV_INLINE +ulint +mach_decode_2( +/*==========*/ + /* out: integer in machine-dependent format */ + uint16 n) /* in: 16-bit integer in canonical format */ +{ + ut_ad(2 == sizeof n); + return(mach_read_from_2((const byte*) &n)); +} + +/*********************************************************** +The following function is used to store data in 3 consecutive +bytes. We store the most significant byte to the lowest address. */ +UNIV_INLINE +void +mach_write_to_3( +/*============*/ + byte* b, /* in: pointer to 3 bytes where to store */ + ulint n) /* in: ulint integer to be stored */ +{ + ut_ad(b); + ut_ad(n <= 0xFFFFFFUL); + + b[0] = (byte)(n >> 16); + b[1] = (byte)(n >> 8); + b[2] = (byte)(n); +} + +/************************************************************ +The following function is used to fetch data from 3 consecutive +bytes. The most significant byte is at the lowest address. */ +UNIV_INLINE +ulint +mach_read_from_3( +/*=============*/ + /* out: ulint integer */ + const byte* b) /* in: pointer to 3 bytes */ +{ + ut_ad(b); + return( ((ulint)(b[0]) << 16) + + ((ulint)(b[1]) << 8) + + (ulint)(b[2]) + ); +} + +/*********************************************************** +The following function is used to store data in four consecutive +bytes. We store the most significant byte to the lowest address. */ +UNIV_INLINE +void +mach_write_to_4( +/*============*/ + byte* b, /* in: pointer to four bytes where to store */ + ulint n) /* in: ulint integer to be stored */ +{ + ut_ad(b); + + b[0] = (byte)(n >> 24); + b[1] = (byte)(n >> 16); + b[2] = (byte)(n >> 8); + b[3] = (byte)n; +} + +/************************************************************ +The following function is used to fetch data from 4 consecutive +bytes. The most significant byte is at the lowest address. */ +UNIV_INLINE +ulint +mach_read_from_4( +/*=============*/ + /* out: ulint integer */ + const byte* b) /* in: pointer to four bytes */ +{ + ut_ad(b); + return( ((ulint)(b[0]) << 24) + + ((ulint)(b[1]) << 16) + + ((ulint)(b[2]) << 8) + + (ulint)(b[3]) + ); +} + +/************************************************************* +Writes a ulint in a compressed form where the first byte codes the +length of the stored ulint. We look at the most significant bits of +the byte. If the most significant bit is zero, it means 1-byte storage, +else if the 2nd bit is 0, it means 2-byte storage, else if 3rd is 0, +it means 3-byte storage, else if 4th is 0, it means 4-byte storage, +else the storage is 5-byte. */ +UNIV_INLINE +ulint +mach_write_compressed( +/*==================*/ + /* out: compressed size in bytes */ + byte* b, /* in: pointer to memory where to store */ + ulint n) /* in: ulint integer (< 2^32) to be stored */ +{ + ut_ad(b); + + if (n < 0x80UL) { + mach_write_to_1(b, n); + return(1); + } else if (n < 0x4000UL) { + mach_write_to_2(b, n | 0x8000UL); + return(2); + } else if (n < 0x200000UL) { + mach_write_to_3(b, n | 0xC00000UL); + return(3); + } else if (n < 0x10000000UL) { + mach_write_to_4(b, n | 0xE0000000UL); + return(4); + } else { + mach_write_to_1(b, 0xF0UL); + mach_write_to_4(b + 1, n); + return(5); + } +} + +/************************************************************* +Returns the size of a ulint when written in the compressed form. */ +UNIV_INLINE +ulint +mach_get_compressed_size( +/*=====================*/ + /* out: compressed size in bytes */ + ulint n) /* in: ulint integer (< 2^32) to be stored */ +{ + if (n < 0x80UL) { + return(1); + } else if (n < 0x4000UL) { + return(2); + } else if (n < 0x200000UL) { + return(3); + } else if (n < 0x10000000UL) { + return(4); + } else { + return(5); + } +} + +/************************************************************* +Reads a ulint in a compressed form. */ +UNIV_INLINE +ulint +mach_read_compressed( +/*=================*/ + /* out: read integer (< 2^32) */ + const byte* b) /* in: pointer to memory from where to read */ +{ + ulint flag; + + ut_ad(b); + + flag = mach_read_from_1(b); + + if (flag < 0x80UL) { + return(flag); + } else if (flag < 0xC0UL) { + return(mach_read_from_2(b) & 0x7FFFUL); + } else if (flag < 0xE0UL) { + return(mach_read_from_3(b) & 0x3FFFFFUL); + } else if (flag < 0xF0UL) { + return(mach_read_from_4(b) & 0x1FFFFFFFUL); + } else { + ut_ad(flag == 0xF0UL); + return(mach_read_from_4(b + 1)); + } +} + +/*********************************************************** +The following function is used to store data in 8 consecutive +bytes. We store the most significant byte to the lowest address. */ +UNIV_INLINE +void +mach_write_to_8( +/*============*/ + byte* b, /* in: pointer to 8 bytes where to store */ + dulint n) /* in: dulint integer to be stored */ +{ + ut_ad(b); + + mach_write_to_4(b, ut_dulint_get_high(n)); + mach_write_to_4(b + 4, ut_dulint_get_low(n)); +} + +/*********************************************************** +The following function is used to store data in 8 consecutive +bytes. We store the most significant byte to the lowest address. */ +UNIV_INLINE +void +mach_write_ull( +/*===========*/ + byte* b, /* in: pointer to 8 bytes where to store */ + ib_uint64_t n) /* in: 64-bit integer to be stored */ +{ + ut_ad(b); + + mach_write_to_4(b, (ulint) (n >> 32)); + mach_write_to_4(b + 4, (ulint) n); +} + +/************************************************************ +The following function is used to fetch data from 8 consecutive +bytes. The most significant byte is at the lowest address. */ +UNIV_INLINE +dulint +mach_read_from_8( +/*=============*/ + /* out: dulint integer */ + const byte* b) /* in: pointer to 8 bytes */ +{ + ulint high; + ulint low; + + ut_ad(b); + + high = mach_read_from_4(b); + low = mach_read_from_4(b + 4); + + return(ut_dulint_create(high, low)); +} + +/************************************************************ +The following function is used to fetch data from 8 consecutive +bytes. The most significant byte is at the lowest address. */ +UNIV_INLINE +ib_uint64_t +mach_read_ull( +/*==========*/ + /* out: 64-bit integer */ + const byte* b) /* in: pointer to 8 bytes */ +{ + ib_uint64_t ull; + + ull = ((ib_uint64_t) mach_read_from_4(b)) << 32; + ull |= (ib_uint64_t) mach_read_from_4(b + 4); + + return(ull); +} + +/*********************************************************** +The following function is used to store data in 7 consecutive +bytes. We store the most significant byte to the lowest address. */ +UNIV_INLINE +void +mach_write_to_7( +/*============*/ + byte* b, /* in: pointer to 7 bytes where to store */ + dulint n) /* in: dulint integer to be stored */ +{ + ut_ad(b); + + mach_write_to_3(b, ut_dulint_get_high(n)); + mach_write_to_4(b + 3, ut_dulint_get_low(n)); +} + +/************************************************************ +The following function is used to fetch data from 7 consecutive +bytes. The most significant byte is at the lowest address. */ +UNIV_INLINE +dulint +mach_read_from_7( +/*=============*/ + /* out: dulint integer */ + const byte* b) /* in: pointer to 7 bytes */ +{ + ulint high; + ulint low; + + ut_ad(b); + + high = mach_read_from_3(b); + low = mach_read_from_4(b + 3); + + return(ut_dulint_create(high, low)); +} + +/*********************************************************** +The following function is used to store data in 6 consecutive +bytes. We store the most significant byte to the lowest address. */ +UNIV_INLINE +void +mach_write_to_6( +/*============*/ + byte* b, /* in: pointer to 6 bytes where to store */ + dulint n) /* in: dulint integer to be stored */ +{ + ut_ad(b); + + mach_write_to_2(b, ut_dulint_get_high(n)); + mach_write_to_4(b + 2, ut_dulint_get_low(n)); +} + +/************************************************************ +The following function is used to fetch data from 6 consecutive +bytes. The most significant byte is at the lowest address. */ +UNIV_INLINE +dulint +mach_read_from_6( +/*=============*/ + /* out: dulint integer */ + const byte* b) /* in: pointer to 6 bytes */ +{ + ulint high; + ulint low; + + ut_ad(b); + + high = mach_read_from_2(b); + low = mach_read_from_4(b + 2); + + return(ut_dulint_create(high, low)); +} + +/************************************************************* +Writes a dulint in a compressed form (5..9 bytes). */ +UNIV_INLINE +ulint +mach_dulint_write_compressed( +/*=========================*/ + /* out: size in bytes */ + byte* b, /* in: pointer to memory where to store */ + dulint n) /* in: dulint integer to be stored */ +{ + ulint size; + + ut_ad(b); + + size = mach_write_compressed(b, ut_dulint_get_high(n)); + mach_write_to_4(b + size, ut_dulint_get_low(n)); + + return(size + 4); +} + +/************************************************************* +Returns the size of a dulint when written in the compressed form. */ +UNIV_INLINE +ulint +mach_dulint_get_compressed_size( +/*============================*/ + /* out: compressed size in bytes */ + dulint n) /* in: dulint integer to be stored */ +{ + return(4 + mach_get_compressed_size(ut_dulint_get_high(n))); +} + +/************************************************************* +Reads a dulint in a compressed form. */ +UNIV_INLINE +dulint +mach_dulint_read_compressed( +/*========================*/ + /* out: read dulint */ + const byte* b) /* in: pointer to memory from where to read */ +{ + ulint high; + ulint low; + ulint size; + + ut_ad(b); + + high = mach_read_compressed(b); + + size = mach_get_compressed_size(high); + + low = mach_read_from_4(b + size); + + return(ut_dulint_create(high, low)); +} + +/************************************************************* +Writes a dulint in a compressed form (1..11 bytes). */ +UNIV_INLINE +ulint +mach_dulint_write_much_compressed( +/*==============================*/ + /* out: size in bytes */ + byte* b, /* in: pointer to memory where to store */ + dulint n) /* in: dulint integer to be stored */ +{ + ulint size; + + ut_ad(b); + + if (ut_dulint_get_high(n) == 0) { + return(mach_write_compressed(b, ut_dulint_get_low(n))); + } + + *b = (byte)0xFF; + size = 1 + mach_write_compressed(b + 1, ut_dulint_get_high(n)); + + size += mach_write_compressed(b + size, ut_dulint_get_low(n)); + + return(size); +} + +/************************************************************* +Returns the size of a dulint when written in the compressed form. */ +UNIV_INLINE +ulint +mach_dulint_get_much_compressed_size( +/*=================================*/ + /* out: compressed size in bytes */ + dulint n) /* in: dulint integer to be stored */ +{ + if (0 == ut_dulint_get_high(n)) { + return(mach_get_compressed_size(ut_dulint_get_low(n))); + } + + return(1 + mach_get_compressed_size(ut_dulint_get_high(n)) + + mach_get_compressed_size(ut_dulint_get_low(n))); +} + +/************************************************************* +Reads a dulint in a compressed form. */ +UNIV_INLINE +dulint +mach_dulint_read_much_compressed( +/*=============================*/ + /* out: read dulint */ + const byte* b) /* in: pointer to memory from where to read */ +{ + ulint high; + ulint low; + ulint size; + + ut_ad(b); + + if (*b != (byte)0xFF) { + high = 0; + size = 0; + } else { + high = mach_read_compressed(b + 1); + + size = 1 + mach_get_compressed_size(high); + } + + low = mach_read_compressed(b + size); + + return(ut_dulint_create(high, low)); +} + +/************************************************************* +Reads a double. It is stored in a little-endian format. */ +UNIV_INLINE +double +mach_double_read( +/*=============*/ + /* out: double read */ + const byte* b) /* in: pointer to memory from where to read */ +{ + double d; + ulint i; + byte* ptr; + + ptr = (byte*)&d; + + for (i = 0; i < sizeof(double); i++) { +#ifdef WORDS_BIGENDIAN + ptr[sizeof(double) - i - 1] = b[i]; +#else + ptr[i] = b[i]; +#endif + } + + return(d); +} + +/************************************************************* +Writes a double. It is stored in a little-endian format. */ +UNIV_INLINE +void +mach_double_write( +/*==============*/ + byte* b, /* in: pointer to memory where to write */ + double d) /* in: double */ +{ + ulint i; + byte* ptr; + + ptr = (byte*)&d; + + for (i = 0; i < sizeof(double); i++) { +#ifdef WORDS_BIGENDIAN + b[i] = ptr[sizeof(double) - i - 1]; +#else + b[i] = ptr[i]; +#endif + } +} + +/************************************************************* +Reads a float. It is stored in a little-endian format. */ +UNIV_INLINE +float +mach_float_read( +/*============*/ + /* out: float read */ + const byte* b) /* in: pointer to memory from where to read */ +{ + float d; + ulint i; + byte* ptr; + + ptr = (byte*)&d; + + for (i = 0; i < sizeof(float); i++) { +#ifdef WORDS_BIGENDIAN + ptr[sizeof(float) - i - 1] = b[i]; +#else + ptr[i] = b[i]; +#endif + } + + return(d); +} + +/************************************************************* +Writes a float. It is stored in a little-endian format. */ +UNIV_INLINE +void +mach_float_write( +/*=============*/ + byte* b, /* in: pointer to memory where to write */ + float d) /* in: float */ +{ + ulint i; + byte* ptr; + + ptr = (byte*)&d; + + for (i = 0; i < sizeof(float); i++) { +#ifdef WORDS_BIGENDIAN + b[i] = ptr[sizeof(float) - i - 1]; +#else + b[i] = ptr[i]; +#endif + } +} + +/************************************************************* +Reads a ulint stored in the little-endian format. */ +UNIV_INLINE +ulint +mach_read_from_n_little_endian( +/*===========================*/ + /* out: unsigned long int */ + const byte* buf, /* in: from where to read */ + ulint buf_size) /* in: from how many bytes to read */ +{ + ulint n = 0; + const byte* ptr; + + ut_ad(buf_size <= sizeof(ulint)); + ut_ad(buf_size > 0); + + ptr = buf + buf_size; + + for (;;) { + ptr--; + + n = n << 8; + + n += (ulint)(*ptr); + + if (ptr == buf) { + break; + } + } + + return(n); +} + +/************************************************************* +Writes a ulint in the little-endian format. */ +UNIV_INLINE +void +mach_write_to_n_little_endian( +/*==========================*/ + byte* dest, /* in: where to write */ + ulint dest_size, /* in: into how many bytes to write */ + ulint n) /* in: unsigned long int to write */ +{ + byte* end; + + ut_ad(dest_size <= sizeof(ulint)); + ut_ad(dest_size > 0); + + end = dest + dest_size; + + for (;;) { + *dest = (byte)(n & 0xFF); + + n = n >> 8; + + dest++; + + if (dest == end) { + break; + } + } + + ut_ad(n == 0); +} + +/************************************************************* +Reads a ulint stored in the little-endian format. */ +UNIV_INLINE +ulint +mach_read_from_2_little_endian( +/*===========================*/ + /* out: unsigned long int */ + const byte* buf) /* in: from where to read */ +{ + return((ulint)(*buf) + ((ulint)(*(buf + 1))) * 256); +} + +/************************************************************* +Writes a ulint in the little-endian format. */ +UNIV_INLINE +void +mach_write_to_2_little_endian( +/*==========================*/ + byte* dest, /* in: where to write */ + ulint n) /* in: unsigned long int to write */ +{ + ut_ad(n < 256 * 256); + + *dest = (byte)(n & 0xFFUL); + + n = n >> 8; + dest++; + + *dest = (byte)(n & 0xFFUL); +} + +/************************************************************* +Convert integral type from storage byte order (big endian) to +host byte order. */ +UNIV_INLINE +ullint +mach_read_int_type( +/*===============*/ + /* out: integer value */ + const byte* src, /* in: where to read from */ + ulint len, /* in: length of src */ + ibool unsigned_type) /* in: signed or unsigned flag */ +{ + /* XXX this can be optimized on big-endian machines */ + + ullint ret; + uint i; + + if (unsigned_type || (src[0] & 0x80)) { + + ret = 0x0000000000000000ULL; + } else { + + ret = 0xFFFFFFFFFFFFFF00ULL; + } + + if (unsigned_type) { + + ret |= src[0]; + } else { + + ret |= src[0] ^ 0x80; + } + + for (i = 1; i < len; i++) { + ret <<= 8; + ret |= src[i]; + } + + return(ret); +} |