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., 59 Temple
15
Place, Suite 330, Boston, MA 02111-1307 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 */
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 */
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 */
85
return( ((ulint)(b[0]) << 8)
90
/********************************************************//**
91
The following function is used to convert a 16-bit data item
92
to the canonical format, for fast bytewise equality test
94
@return 16-bit integer in canonical format */
99
ulint n) /*!< in: integer in machine-dependent format */
102
ut_ad(2 == sizeof ret);
103
mach_write_to_2((byte*) &ret, n);
106
/********************************************************//**
107
The following function is used to convert a 16-bit data item
108
from the canonical format, for fast bytewise equality test
110
@return integer in machine-dependent format */
115
uint16 n) /*!< in: 16-bit integer in canonical format */
117
ut_ad(2 == sizeof n);
118
return(mach_read_from_2((const byte*) &n));
121
/*******************************************************//**
122
The following function is used to store data in 3 consecutive
123
bytes. We store the most significant byte to the lowest address. */
128
byte* b, /*!< in: pointer to 3 bytes where to store */
129
ulint n) /*!< in: ulint integer to be stored */
132
ut_ad(n <= 0xFFFFFFUL);
134
b[0] = (byte)(n >> 16);
135
b[1] = (byte)(n >> 8);
139
/********************************************************//**
140
The following function is used to fetch data from 3 consecutive
141
bytes. The most significant byte is at the lowest address.
142
@return ulint integer */
147
const byte* b) /*!< in: pointer to 3 bytes */
150
return( ((ulint)(b[0]) << 16)
151
+ ((ulint)(b[1]) << 8)
156
/*******************************************************//**
157
The following function is used to store data in four consecutive
158
bytes. We store the most significant byte to the lowest address. */
163
byte* b, /*!< in: pointer to four bytes where to store */
164
ulint n) /*!< in: ulint integer to be stored */
168
b[0] = (byte)(n >> 24);
169
b[1] = (byte)(n >> 16);
170
b[2] = (byte)(n >> 8);
174
/********************************************************//**
175
The following function is used to fetch data from 4 consecutive
176
bytes. The most significant byte is at the lowest address.
177
@return ulint integer */
182
const byte* b) /*!< in: pointer to four bytes */
185
return( ((ulint)(b[0]) << 24)
186
+ ((ulint)(b[1]) << 16)
187
+ ((ulint)(b[2]) << 8)
192
/*********************************************************//**
193
Writes a ulint in a compressed form where the first byte codes the
194
length of the stored ulint. We look at the most significant bits of
195
the byte. If the most significant bit is zero, it means 1-byte storage,
196
else if the 2nd bit is 0, it means 2-byte storage, else if 3rd is 0,
197
it means 3-byte storage, else if 4th is 0, it means 4-byte storage,
198
else the storage is 5-byte.
199
@return compressed size in bytes */
202
mach_write_compressed(
203
/*==================*/
204
byte* b, /*!< in: pointer to memory where to store */
205
ulint n) /*!< in: ulint integer (< 2^32) to be stored */
210
mach_write_to_1(b, n);
212
} else if (n < 0x4000UL) {
213
mach_write_to_2(b, n | 0x8000UL);
215
} else if (n < 0x200000UL) {
216
mach_write_to_3(b, n | 0xC00000UL);
218
} else if (n < 0x10000000UL) {
219
mach_write_to_4(b, n | 0xE0000000UL);
222
mach_write_to_1(b, 0xF0UL);
223
mach_write_to_4(b + 1, n);
228
/*********************************************************//**
229
Returns the size of a ulint when written in the compressed form.
230
@return compressed size in bytes */
233
mach_get_compressed_size(
234
/*=====================*/
235
ulint n) /*!< in: ulint integer (< 2^32) to be stored */
239
} else if (n < 0x4000UL) {
241
} else if (n < 0x200000UL) {
243
} else if (n < 0x10000000UL) {
250
/*********************************************************//**
251
Reads a ulint in a compressed form.
252
@return read integer (< 2^32) */
255
mach_read_compressed(
256
/*=================*/
257
const byte* b) /*!< in: pointer to memory from where to read */
263
flag = mach_read_from_1(b);
267
} else if (flag < 0xC0UL) {
268
return(mach_read_from_2(b) & 0x7FFFUL);
269
} else if (flag < 0xE0UL) {
270
return(mach_read_from_3(b) & 0x3FFFFFUL);
271
} else if (flag < 0xF0UL) {
272
return(mach_read_from_4(b) & 0x1FFFFFFFUL);
274
ut_ad(flag == 0xF0UL);
275
return(mach_read_from_4(b + 1));
279
/*******************************************************//**
280
The following function is used to store data in 8 consecutive
281
bytes. We store the most significant byte to the lowest address. */
286
byte* b, /*!< in: pointer to 8 bytes where to store */
287
dulint n) /*!< in: dulint integer to be stored */
291
mach_write_to_4(b, ut_dulint_get_high(n));
292
mach_write_to_4(b + 4, ut_dulint_get_low(n));
295
/*******************************************************//**
296
The following function is used to store data in 8 consecutive
297
bytes. We store the most significant byte to the lowest address. */
302
byte* b, /*!< in: pointer to 8 bytes where to store */
303
ib_uint64_t n) /*!< in: 64-bit integer to be stored */
307
mach_write_to_4(b, (ulint) (n >> 32));
308
mach_write_to_4(b + 4, (ulint) n);
311
/********************************************************//**
312
The following function is used to fetch data from 8 consecutive
313
bytes. The most significant byte is at the lowest address.
314
@return dulint integer */
319
const byte* b) /*!< in: pointer to 8 bytes */
326
high = mach_read_from_4(b);
327
low = mach_read_from_4(b + 4);
329
return(ut_dulint_create(high, low));
332
/********************************************************//**
333
The following function is used to fetch data from 8 consecutive
334
bytes. The most significant byte is at the lowest address.
335
@return 64-bit integer */
340
const byte* b) /*!< in: pointer to 8 bytes */
344
ull = ((ib_uint64_t) mach_read_from_4(b)) << 32;
345
ull |= (ib_uint64_t) mach_read_from_4(b + 4);
350
/*******************************************************//**
351
The following function is used to store data in 7 consecutive
352
bytes. We store the most significant byte to the lowest address. */
357
byte* b, /*!< in: pointer to 7 bytes where to store */
358
dulint n) /*!< in: dulint integer to be stored */
362
mach_write_to_3(b, ut_dulint_get_high(n));
363
mach_write_to_4(b + 3, ut_dulint_get_low(n));
366
/********************************************************//**
367
The following function is used to fetch data from 7 consecutive
368
bytes. The most significant byte is at the lowest address.
369
@return dulint integer */
374
const byte* b) /*!< in: pointer to 7 bytes */
381
high = mach_read_from_3(b);
382
low = mach_read_from_4(b + 3);
384
return(ut_dulint_create(high, low));
387
/*******************************************************//**
388
The following function is used to store data in 6 consecutive
389
bytes. We store the most significant byte to the lowest address. */
394
byte* b, /*!< in: pointer to 6 bytes where to store */
395
dulint n) /*!< in: dulint integer to be stored */
399
mach_write_to_2(b, ut_dulint_get_high(n));
400
mach_write_to_4(b + 2, ut_dulint_get_low(n));
403
/********************************************************//**
404
The following function is used to fetch data from 6 consecutive
405
bytes. The most significant byte is at the lowest address.
406
@return dulint integer */
411
const byte* b) /*!< in: pointer to 6 bytes */
418
high = mach_read_from_2(b);
419
low = mach_read_from_4(b + 2);
421
return(ut_dulint_create(high, low));
424
/*********************************************************//**
425
Writes a dulint in a compressed form (5..9 bytes).
426
@return size in bytes */
429
mach_dulint_write_compressed(
430
/*=========================*/
431
byte* b, /*!< in: pointer to memory where to store */
432
dulint n) /*!< in: dulint integer to be stored */
438
size = mach_write_compressed(b, ut_dulint_get_high(n));
439
mach_write_to_4(b + size, ut_dulint_get_low(n));
444
/*********************************************************//**
445
Returns the size of a dulint when written in the compressed form.
446
@return compressed size in bytes */
449
mach_dulint_get_compressed_size(
450
/*============================*/
451
dulint n) /*!< in: dulint integer to be stored */
453
return(4 + mach_get_compressed_size(ut_dulint_get_high(n)));
456
/*********************************************************//**
457
Reads a dulint in a compressed form.
458
@return read dulint */
461
mach_dulint_read_compressed(
462
/*========================*/
463
const byte* b) /*!< in: pointer to memory from where to read */
471
high = mach_read_compressed(b);
473
size = mach_get_compressed_size(high);
475
low = mach_read_from_4(b + size);
477
return(ut_dulint_create(high, low));
480
/*********************************************************//**
481
Writes a dulint in a compressed form (1..11 bytes).
482
@return size in bytes */
485
mach_dulint_write_much_compressed(
486
/*==============================*/
487
byte* b, /*!< in: pointer to memory where to store */
488
dulint n) /*!< in: dulint integer to be stored */
494
if (ut_dulint_get_high(n) == 0) {
495
return(mach_write_compressed(b, ut_dulint_get_low(n)));
499
size = 1 + mach_write_compressed(b + 1, ut_dulint_get_high(n));
501
size += mach_write_compressed(b + size, ut_dulint_get_low(n));
506
/*********************************************************//**
507
Returns the size of a dulint when written in the compressed form.
508
@return compressed size in bytes */
511
mach_dulint_get_much_compressed_size(
512
/*=================================*/
513
dulint n) /*!< in: dulint integer to be stored */
515
if (0 == ut_dulint_get_high(n)) {
516
return(mach_get_compressed_size(ut_dulint_get_low(n)));
519
return(1 + mach_get_compressed_size(ut_dulint_get_high(n))
520
+ mach_get_compressed_size(ut_dulint_get_low(n)));
523
/*********************************************************//**
524
Reads a dulint in a compressed form.
525
@return read dulint */
528
mach_dulint_read_much_compressed(
529
/*=============================*/
530
const byte* b) /*!< in: pointer to memory from where to read */
538
if (*b != (byte)0xFF) {
542
high = mach_read_compressed(b + 1);
544
size = 1 + mach_get_compressed_size(high);
547
low = mach_read_compressed(b + size);
549
return(ut_dulint_create(high, low));
551
#ifndef UNIV_HOTBACKUP
552
/*********************************************************//**
553
Reads a double. It is stored in a little-endian format.
554
@return double read */
559
const byte* b) /*!< in: pointer to memory from where to read */
567
for (i = 0; i < sizeof(double); i++) {
568
#ifdef WORDS_BIGENDIAN
569
ptr[sizeof(double) - i - 1] = b[i];
578
/*********************************************************//**
579
Writes a double. It is stored in a little-endian format. */
584
byte* b, /*!< in: pointer to memory where to write */
585
double d) /*!< in: double */
592
for (i = 0; i < sizeof(double); i++) {
593
#ifdef WORDS_BIGENDIAN
594
b[i] = ptr[sizeof(double) - i - 1];
601
/*********************************************************//**
602
Reads a float. It is stored in a little-endian format.
603
@return float read */
608
const byte* b) /*!< in: pointer to memory from where to read */
616
for (i = 0; i < sizeof(float); i++) {
617
#ifdef WORDS_BIGENDIAN
618
ptr[sizeof(float) - i - 1] = b[i];
627
/*********************************************************//**
628
Writes a float. It is stored in a little-endian format. */
633
byte* b, /*!< in: pointer to memory where to write */
634
float d) /*!< in: float */
641
for (i = 0; i < sizeof(float); i++) {
642
#ifdef WORDS_BIGENDIAN
643
b[i] = ptr[sizeof(float) - i - 1];
650
/*********************************************************//**
651
Reads a ulint stored in the little-endian format.
652
@return unsigned long int */
655
mach_read_from_n_little_endian(
656
/*===========================*/
657
const byte* buf, /*!< in: from where to read */
658
ulint buf_size) /*!< in: from how many bytes to read */
663
ut_ad(buf_size <= sizeof(ulint));
666
ptr = buf + buf_size;
683
/*********************************************************//**
684
Writes a ulint in the little-endian format. */
687
mach_write_to_n_little_endian(
688
/*==========================*/
689
byte* dest, /*!< in: where to write */
690
ulint dest_size, /*!< in: into how many bytes to write */
691
ulint n) /*!< in: unsigned long int to write */
695
ut_ad(dest_size <= sizeof(ulint));
696
ut_ad(dest_size > 0);
698
end = dest + dest_size;
701
*dest = (byte)(n & 0xFF);
715
/*********************************************************//**
716
Reads a ulint stored in the little-endian format.
717
@return unsigned long int */
720
mach_read_from_2_little_endian(
721
/*===========================*/
722
const byte* buf) /*!< in: from where to read */
724
return((ulint)(*buf) + ((ulint)(*(buf + 1))) * 256);
727
/*********************************************************//**
728
Writes a ulint in the little-endian format. */
731
mach_write_to_2_little_endian(
732
/*==========================*/
733
byte* dest, /*!< in: where to write */
734
ulint n) /*!< in: unsigned long int to write */
736
ut_ad(n < 256 * 256);
738
*dest = (byte)(n & 0xFFUL);
743
*dest = (byte)(n & 0xFFUL);
746
/*********************************************************//**
747
Convert integral type from storage byte order (big endian) to
749
@return integer value */
754
const byte* src, /*!< in: where to read from */
755
ulint len, /*!< in: length of src */
756
ibool unsigned_type) /*!< in: signed or unsigned flag */
758
/* XXX this can be optimized on big-endian machines */
763
if (unsigned_type || (src[0] & 0x80)) {
765
ret = 0x0000000000000000ULL;
768
ret = 0xFFFFFFFFFFFFFF00ULL;
776
ret |= src[0] ^ 0x80;
779
for (i = 1; i < len; i++) {
786
#endif /* !UNIV_HOTBACKUP */