summaryrefslogtreecommitdiff
path: root/storage/xtradb/include/mach0data.ic
diff options
context:
space:
mode:
Diffstat (limited to 'storage/xtradb/include/mach0data.ic')
-rw-r--r--storage/xtradb/include/mach0data.ic784
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);
+}