mirror of
https://github.com/MariaDB/server.git
synced 2025-01-27 17:33:44 +01:00
e8435b3e45
and lexer files). From now on, the following Emacs cc-mode settings apply when indenting C function bodies in InnoDB: (setq c-basic-offset 8) (setq c-label-minimum-indentation 0) (add-to-list 'c-offsets-alist '(c . 0)) (add-to-list 'c-offsets-alist '(label . [0])) The indentation rules for function declarations still have not been formalized, and they must be formatted manually. Try to limit all lines to at most 79 characters (assuming TAB stops every 8 characters) by splitting lines before opening parenthesis, or at string constants. Fix some grammar mistakes in diagnostic output: match to, match with -> match found from -> found in trying rename -> trying to rename Fix an error in page_check_dir(): it said "supremum not pointed to" when the infimum was not pointed to. Enclose commented-out code snippets in #if 0 ... #endif instead of /* ... */. Add (void*) casts to some %p parameters in fprintf() calls. Try to split lines before a binary operator, not after one. (These three fixes were not made everywhere.)
691 lines
16 KiB
Text
691 lines
16 KiB
Text
/**********************************************************************
|
|
Utilities for converting data from the database file
|
|
to the machine format.
|
|
|
|
(c) 1995 Innobase Oy
|
|
|
|
Created 11/28/1995 Heikki Tuuri
|
|
***********************************************************************/
|
|
|
|
/***********************************************************
|
|
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 */
|
|
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 */
|
|
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((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 */
|
|
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 */
|
|
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) */
|
|
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 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 */
|
|
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 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 */
|
|
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 */
|
|
byte* b) /* in: pointer to 7 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 */
|
|
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 */
|
|
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 */
|
|
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 */
|
|
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 */
|
|
byte* buf, /* in: from where to read */
|
|
ulint buf_size) /* in: from how many bytes to read */
|
|
{
|
|
ulint n = 0;
|
|
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 */
|
|
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);
|
|
}
|