1
/*****************************************************************************
3
Copyright (C) 1995, 2009, Innobase Oy. All Rights Reserved.
5
This program is free software; you can redistribute it and/or modify it under
6
the terms of the GNU General Public License as published by the Free Software
7
Foundation; version 2 of the License.
9
This program is distributed in the hope that it will be useful, but WITHOUT
10
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
You should have received a copy of the GNU General Public License along with
14
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
15
St, Fifth Floor, Boston, MA 02110-1301 USA
17
*****************************************************************************/
19
/******************************************************************//**
20
@file include/mach0data.ic
21
Utilities for converting data from the database file
22
to the machine format.
24
Created 11/28/1995 Heikki Tuuri
25
***********************************************************************/
29
/*******************************************************//**
30
The following function is used to store data in one byte. */
35
byte* b, /*!< in: pointer to byte where to store */
36
ulint n) /*!< in: ulint integer to be stored, >= 0, < 256 */
39
ut_ad((n | 0xFFUL) <= 0xFFUL);
44
/********************************************************//**
45
The following function is used to fetch data from one byte.
46
@return ulint integer, >= 0, < 256 */
51
const byte* b) /*!< in: pointer to byte */
54
return((ulint)(b[0]));
57
/*******************************************************//**
58
The following function is used to store data in two consecutive
59
bytes. We store the most significant byte to the lowest address. */
64
byte* b, /*!< in: pointer to two bytes where to store */
65
ulint n) /*!< in: ulint integer to be stored */
68
ut_ad((n | 0xFFFFUL) <= 0xFFFFUL);
70
b[0] = (byte)(n >> 8);
74
/********************************************************//**
75
The following function is used to fetch data from 2 consecutive
76
bytes. The most significant byte is at the lowest address.
77
@return ulint integer */
82
const byte* b) /*!< in: pointer to 2 bytes */
84
return(((ulint)(b[0]) << 8) | (ulint)(b[1]));
87
/********************************************************//**
88
The following function is used to convert a 16-bit data item
89
to the canonical format, for fast bytewise equality test
91
@return 16-bit integer in canonical format */
96
ulint n) /*!< in: integer in machine-dependent format */
99
ut_ad(2 == sizeof ret);
100
mach_write_to_2((byte*) &ret, n);
103
/********************************************************//**
104
The following function is used to convert a 16-bit data item
105
from the canonical format, for fast bytewise equality test
107
@return integer in machine-dependent format */
112
uint16 n) /*!< in: 16-bit integer in canonical format */
114
ut_ad(2 == sizeof n);
115
return(mach_read_from_2((const byte*) &n));
118
/*******************************************************//**
119
The following function is used to store data in 3 consecutive
120
bytes. We store the most significant byte to the lowest address. */
125
byte* b, /*!< in: pointer to 3 bytes where to store */
126
ulint n) /*!< in: ulint integer to be stored */
129
ut_ad((n | 0xFFFFFFUL) <= 0xFFFFFFUL);
131
b[0] = (byte)(n >> 16);
132
b[1] = (byte)(n >> 8);
136
/********************************************************//**
137
The following function is used to fetch data from 3 consecutive
138
bytes. The most significant byte is at the lowest address.
139
@return ulint integer */
144
const byte* b) /*!< in: pointer to 3 bytes */
147
return( ((ulint)(b[0]) << 16)
148
| ((ulint)(b[1]) << 8)
153
/*******************************************************//**
154
The following function is used to store data in four consecutive
155
bytes. We store the most significant byte to the lowest address. */
160
byte* b, /*!< in: pointer to four bytes where to store */
161
ulint n) /*!< in: ulint integer to be stored */
165
b[0] = (byte)(n >> 24);
166
b[1] = (byte)(n >> 16);
167
b[2] = (byte)(n >> 8);
171
/********************************************************//**
172
The following function is used to fetch data from 4 consecutive
173
bytes. The most significant byte is at the lowest address.
174
@return ulint integer */
179
const byte* b) /*!< in: pointer to four bytes */
182
return( ((ulint)(b[0]) << 24)
183
| ((ulint)(b[1]) << 16)
184
| ((ulint)(b[2]) << 8)
189
/*********************************************************//**
190
Writes a ulint in a compressed form where the first byte codes the
191
length of the stored ulint. We look at the most significant bits of
192
the byte. If the most significant bit is zero, it means 1-byte storage,
193
else if the 2nd bit is 0, it means 2-byte storage, else if 3rd is 0,
194
it means 3-byte storage, else if 4th is 0, it means 4-byte storage,
195
else the storage is 5-byte.
196
@return compressed size in bytes */
199
mach_write_compressed(
200
/*==================*/
201
byte* b, /*!< in: pointer to memory where to store */
202
ulint n) /*!< in: ulint integer (< 2^32) to be stored */
207
mach_write_to_1(b, n);
209
} else if (n < 0x4000UL) {
210
mach_write_to_2(b, n | 0x8000UL);
212
} else if (n < 0x200000UL) {
213
mach_write_to_3(b, n | 0xC00000UL);
215
} else if (n < 0x10000000UL) {
216
mach_write_to_4(b, n | 0xE0000000UL);
219
mach_write_to_1(b, 0xF0UL);
220
mach_write_to_4(b + 1, n);
225
/*********************************************************//**
226
Returns the size of a ulint when written in the compressed form.
227
@return compressed size in bytes */
230
mach_get_compressed_size(
231
/*=====================*/
232
ulint n) /*!< in: ulint integer (< 2^32) to be stored */
236
} else if (n < 0x4000UL) {
238
} else if (n < 0x200000UL) {
240
} else if (n < 0x10000000UL) {
247
/*********************************************************//**
248
Reads a ulint in a compressed form.
249
@return read integer (< 2^32) */
252
mach_read_compressed(
253
/*=================*/
254
const byte* b) /*!< in: pointer to memory from where to read */
260
flag = mach_read_from_1(b);
264
} else if (flag < 0xC0UL) {
265
return(mach_read_from_2(b) & 0x7FFFUL);
266
} else if (flag < 0xE0UL) {
267
return(mach_read_from_3(b) & 0x3FFFFFUL);
268
} else if (flag < 0xF0UL) {
269
return(mach_read_from_4(b) & 0x1FFFFFFFUL);
271
ut_ad(flag == 0xF0UL);
272
return(mach_read_from_4(b + 1));
276
/*******************************************************//**
277
The following function is used to store data in 8 consecutive
278
bytes. We store the most significant byte to the lowest address. */
283
byte* b, /*!< in: pointer to 8 bytes where to store */
284
ib_uint64_t n) /*!< in: 64-bit integer to be stored */
288
mach_write_to_4(b, (ulint) (n >> 32));
289
mach_write_to_4(b + 4, (ulint) n);
292
/********************************************************//**
293
The following function is used to fetch data from 8 consecutive
294
bytes. The most significant byte is at the lowest address.
295
@return 64-bit integer */
300
const byte* b) /*!< in: pointer to 8 bytes */
304
ull = ((ib_uint64_t) mach_read_from_4(b)) << 32;
305
ull |= (ib_uint64_t) mach_read_from_4(b + 4);
310
/*******************************************************//**
311
The following function is used to store data in 7 consecutive
312
bytes. We store the most significant byte to the lowest address. */
317
byte* b, /*!< in: pointer to 7 bytes where to store */
318
ib_uint64_t n) /*!< in: 56-bit integer */
322
mach_write_to_3(b, (ulint) (n >> 32));
323
mach_write_to_4(b + 3, (ulint) n);
326
/********************************************************//**
327
The following function is used to fetch data from 7 consecutive
328
bytes. The most significant byte is at the lowest address.
329
@return 56-bit integer */
334
const byte* b) /*!< in: pointer to 7 bytes */
338
return(ut_ull_create(mach_read_from_3(b), mach_read_from_4(b + 3)));
341
/*******************************************************//**
342
The following function is used to store data in 6 consecutive
343
bytes. We store the most significant byte to the lowest address. */
348
byte* b, /*!< in: pointer to 6 bytes where to store */
349
ib_uint64_t n) /*!< in: 48-bit integer */
353
mach_write_to_2(b, (ulint) (n >> 32));
354
mach_write_to_4(b + 2, (ulint) n);
357
/********************************************************//**
358
The following function is used to fetch data from 6 consecutive
359
bytes. The most significant byte is at the lowest address.
360
@return 48-bit integer */
365
const byte* b) /*!< in: pointer to 6 bytes */
369
return(ut_ull_create(mach_read_from_2(b), mach_read_from_4(b + 2)));
372
/*********************************************************//**
373
Writes a 64-bit integer in a compressed form (5..9 bytes).
374
@return size in bytes */
377
mach_ull_write_compressed(
378
/*======================*/
379
byte* b, /*!< in: pointer to memory where to store */
380
ib_uint64_t n) /*!< in: 64-bit integer to be stored */
386
size = mach_write_compressed(b, (ulint) (n >> 32));
387
mach_write_to_4(b + size, (ulint) n);
392
/*********************************************************//**
393
Returns the size of a 64-bit integer when written in the compressed form.
394
@return compressed size in bytes */
397
mach_ull_get_compressed_size(
398
/*=========================*/
399
ib_uint64_t n) /*!< in: 64-bit integer to be stored */
401
return(4 + mach_get_compressed_size((ulint) (n >> 32)));
404
/*********************************************************//**
405
Reads a 64-bit integer in a compressed form.
406
@return the value read */
409
mach_ull_read_compressed(
410
/*=====================*/
411
const byte* b) /*!< in: pointer to memory from where to read */
418
n = (ib_uint64_t) mach_read_compressed(b);
420
size = mach_get_compressed_size((ulint) n);
423
n |= (ib_uint64_t) mach_read_from_4(b + size);
428
/*********************************************************//**
429
Writes a 64-bit integer in a compressed form (1..11 bytes).
430
@return size in bytes */
433
mach_ull_write_much_compressed(
434
/*===========================*/
435
byte* b, /*!< in: pointer to memory where to store */
436
ib_uint64_t n) /*!< in: 64-bit integer to be stored */
443
return(mach_write_compressed(b, (ulint) n));
447
size = 1 + mach_write_compressed(b + 1, (ulint) (n >> 32));
449
size += mach_write_compressed(b + size, (ulint) n & 0xFFFFFFFF);
454
/*********************************************************//**
455
Returns the size of a 64-bit integer when written in the compressed form.
456
@return compressed size in bytes */
459
mach_ull_get_much_compressed_size(
460
/*==============================*/
461
ib_uint64_t n) /*!< in: 64-bit integer to be stored */
464
return(mach_get_compressed_size((ulint) n));
467
return(1 + mach_get_compressed_size((ulint) (n >> 32))
468
+ mach_get_compressed_size((ulint) n & ULINT32_MASK));
471
/*********************************************************//**
472
Reads a 64-bit integer in a compressed form.
473
@return the value read */
476
mach_ull_read_much_compressed(
477
/*==========================*/
478
const byte* b) /*!< in: pointer to memory from where to read */
485
if (*b != (byte)0xFF) {
489
n = (ib_uint64_t) mach_read_compressed(b + 1);
491
size = 1 + mach_get_compressed_size((ulint) n);
495
n |= mach_read_compressed(b + size);
500
/*********************************************************//**
501
Reads a 64-bit integer in a compressed form
502
if the log record fully contains it.
503
@return pointer to end of the stored field, NULL if not complete */
506
mach_ull_parse_compressed(
507
/*======================*/
508
byte* ptr, /* in: pointer to buffer from where to read */
509
byte* end_ptr,/* in: pointer to end of the buffer */
510
ib_uint64_t* val) /* out: read value */
518
if (end_ptr < ptr + 5) {
523
*val = mach_read_compressed(ptr);
525
size = mach_get_compressed_size((ulint) *val);
529
if (end_ptr < ptr + 4) {
535
*val |= mach_read_from_4(ptr);
539
#ifndef UNIV_HOTBACKUP
540
/*********************************************************//**
541
Reads a double. It is stored in a little-endian format.
542
@return double read */
547
const byte* b) /*!< in: pointer to memory from where to read */
555
for (i = 0; i < sizeof(double); i++) {
556
#ifdef WORDS_BIGENDIAN
557
ptr[sizeof(double) - i - 1] = b[i];
566
/*********************************************************//**
567
Writes a double. It is stored in a little-endian format. */
572
byte* b, /*!< in: pointer to memory where to write */
573
double d) /*!< in: double */
580
for (i = 0; i < sizeof(double); i++) {
581
#ifdef WORDS_BIGENDIAN
582
b[i] = ptr[sizeof(double) - i - 1];
589
/*********************************************************//**
590
Reads a float. It is stored in a little-endian format.
591
@return float read */
596
const byte* b) /*!< in: pointer to memory from where to read */
604
for (i = 0; i < sizeof(float); i++) {
605
#ifdef WORDS_BIGENDIAN
606
ptr[sizeof(float) - i - 1] = b[i];
615
/*********************************************************//**
616
Writes a float. It is stored in a little-endian format. */
621
byte* b, /*!< in: pointer to memory where to write */
622
float d) /*!< in: float */
629
for (i = 0; i < sizeof(float); i++) {
630
#ifdef WORDS_BIGENDIAN
631
b[i] = ptr[sizeof(float) - i - 1];
638
/*********************************************************//**
639
Reads a ulint stored in the little-endian format.
640
@return unsigned long int */
643
mach_read_from_n_little_endian(
644
/*===========================*/
645
const byte* buf, /*!< in: from where to read */
646
ulint buf_size) /*!< in: from how many bytes to read */
651
ut_ad(buf_size <= sizeof(ulint));
654
ptr = buf + buf_size;
671
/*********************************************************//**
672
Writes a ulint in the little-endian format. */
675
mach_write_to_n_little_endian(
676
/*==========================*/
677
byte* dest, /*!< in: where to write */
678
ulint dest_size, /*!< in: into how many bytes to write */
679
ulint n) /*!< in: unsigned long int to write */
683
ut_ad(dest_size <= sizeof(ulint));
684
ut_ad(dest_size > 0);
686
end = dest + dest_size;
689
*dest = (byte)(n & 0xFF);
703
/*********************************************************//**
704
Reads a ulint stored in the little-endian format.
705
@return unsigned long int */
708
mach_read_from_2_little_endian(
709
/*===========================*/
710
const byte* buf) /*!< in: from where to read */
712
return((ulint)(buf[0]) | ((ulint)(buf[1]) << 8));
715
/*********************************************************//**
716
Writes a ulint in the little-endian format. */
719
mach_write_to_2_little_endian(
720
/*==========================*/
721
byte* dest, /*!< in: where to write */
722
ulint n) /*!< in: unsigned long int to write */
724
ut_ad(n < 256 * 256);
726
*dest = (byte)(n & 0xFFUL);
731
*dest = (byte)(n & 0xFFUL);
734
/*********************************************************//**
735
Convert integral type from storage byte order (big endian) to
737
@return integer value */
742
const byte* src, /*!< in: where to read from */
743
ulint len, /*!< in: length of src */
744
ibool unsigned_type) /*!< in: signed or unsigned flag */
746
/* XXX this can be optimized on big-endian machines */
751
if (unsigned_type || (src[0] & 0x80)) {
753
ret = 0x0000000000000000ULL;
756
ret = 0xFFFFFFFFFFFFFF00ULL;
764
ret |= src[0] ^ 0x80;
767
for (i = 1; i < len; i++) {
774
#endif /* !UNIV_HOTBACKUP */