1
/**********************************************************************
2
Utilities for converting data from the database file
7
Created 11/28/1995 Heikki Tuuri
8
***********************************************************************/
12
/***********************************************************
13
The following function is used to store data in one byte. */
18
byte* b, /* in: pointer to byte where to store */
19
ulint n) /* in: ulint integer to be stored, >= 0, < 256 */
27
/************************************************************
28
The following function is used to fetch data from one byte. */
33
/* out: ulint integer, >= 0, < 256 */
34
const byte* b) /* in: pointer to byte */
37
return((ulint)(b[0]));
40
/***********************************************************
41
The following function is used to store data in two consecutive
42
bytes. We store the most significant byte to the lowest address. */
47
byte* b, /* in: pointer to two bytes where to store */
48
ulint n) /* in: ulint integer to be stored */
53
b[0] = (byte)(n >> 8);
57
/************************************************************
58
The following function is used to fetch data from 2 consecutive
59
bytes. The most significant byte is at the lowest address. */
64
/* out: ulint integer */
65
const byte* b) /* in: pointer to 2 bytes */
68
return( ((ulint)(b[0]) << 8)
73
/************************************************************
74
The following function is used to convert a 16-bit data item
75
to the canonical format, for fast bytewise equality test
81
/* out: 16-bit integer in canonical format */
82
ulint n) /* in: integer in machine-dependent format */
85
ut_ad(2 == sizeof ret);
86
mach_write_to_2((byte*) &ret, n);
89
/************************************************************
90
The following function is used to convert a 16-bit data item
91
from the canonical format, for fast bytewise equality test
97
/* out: integer in machine-dependent format */
98
uint16 n) /* in: 16-bit integer in canonical format */
100
ut_ad(2 == sizeof n);
101
return(mach_read_from_2((const byte*) &n));
104
/***********************************************************
105
The following function is used to store data in 3 consecutive
106
bytes. We store the most significant byte to the lowest address. */
111
byte* b, /* in: pointer to 3 bytes where to store */
112
ulint n) /* in: ulint integer to be stored */
115
ut_ad(n <= 0xFFFFFFUL);
117
b[0] = (byte)(n >> 16);
118
b[1] = (byte)(n >> 8);
122
/************************************************************
123
The following function is used to fetch data from 3 consecutive
124
bytes. The most significant byte is at the lowest address. */
129
/* out: ulint integer */
130
const byte* b) /* in: pointer to 3 bytes */
133
return( ((ulint)(b[0]) << 16)
134
+ ((ulint)(b[1]) << 8)
139
/***********************************************************
140
The following function is used to store data in four consecutive
141
bytes. We store the most significant byte to the lowest address. */
146
byte* b, /* in: pointer to four bytes where to store */
147
ulint n) /* in: ulint integer to be stored */
151
b[0] = (byte)(n >> 24);
152
b[1] = (byte)(n >> 16);
153
b[2] = (byte)(n >> 8);
157
/************************************************************
158
The following function is used to fetch data from 4 consecutive
159
bytes. The most significant byte is at the lowest address. */
164
/* out: ulint integer */
165
const byte* b) /* in: pointer to four bytes */
168
return( ((ulint)(b[0]) << 24)
169
+ ((ulint)(b[1]) << 16)
170
+ ((ulint)(b[2]) << 8)
175
/*************************************************************
176
Writes a ulint in a compressed form where the first byte codes the
177
length of the stored ulint. We look at the most significant bits of
178
the byte. If the most significant bit is zero, it means 1-byte storage,
179
else if the 2nd bit is 0, it means 2-byte storage, else if 3rd is 0,
180
it means 3-byte storage, else if 4th is 0, it means 4-byte storage,
181
else the storage is 5-byte. */
184
mach_write_compressed(
185
/*==================*/
186
/* out: compressed size in bytes */
187
byte* b, /* in: pointer to memory where to store */
188
ulint n) /* in: ulint integer (< 2^32) to be stored */
193
mach_write_to_1(b, n);
195
} else if (n < 0x4000UL) {
196
mach_write_to_2(b, n | 0x8000UL);
198
} else if (n < 0x200000UL) {
199
mach_write_to_3(b, n | 0xC00000UL);
201
} else if (n < 0x10000000UL) {
202
mach_write_to_4(b, n | 0xE0000000UL);
205
mach_write_to_1(b, 0xF0UL);
206
mach_write_to_4(b + 1, n);
211
/*************************************************************
212
Returns the size of a ulint when written in the compressed form. */
215
mach_get_compressed_size(
216
/*=====================*/
217
/* out: compressed size in bytes */
218
ulint n) /* in: ulint integer (< 2^32) to be stored */
222
} else if (n < 0x4000UL) {
224
} else if (n < 0x200000UL) {
226
} else if (n < 0x10000000UL) {
233
/*************************************************************
234
Reads a ulint in a compressed form. */
237
mach_read_compressed(
238
/*=================*/
239
/* out: read integer (< 2^32) */
240
const byte* b) /* in: pointer to memory from where to read */
246
flag = mach_read_from_1(b);
250
} else if (flag < 0xC0UL) {
251
return(mach_read_from_2(b) & 0x7FFFUL);
252
} else if (flag < 0xE0UL) {
253
return(mach_read_from_3(b) & 0x3FFFFFUL);
254
} else if (flag < 0xF0UL) {
255
return(mach_read_from_4(b) & 0x1FFFFFFFUL);
257
ut_ad(flag == 0xF0UL);
258
return(mach_read_from_4(b + 1));
262
/***********************************************************
263
The following function is used to store data in 8 consecutive
264
bytes. We store the most significant byte to the lowest address. */
269
byte* b, /* in: pointer to 8 bytes where to store */
270
dulint n) /* in: dulint integer to be stored */
274
mach_write_to_4(b, ut_dulint_get_high(n));
275
mach_write_to_4(b + 4, ut_dulint_get_low(n));
278
/***********************************************************
279
The following function is used to store data in 8 consecutive
280
bytes. We store the most significant byte to the lowest address. */
285
byte* b, /* in: pointer to 8 bytes where to store */
286
ib_uint64_t n) /* in: 64-bit integer to be stored */
290
mach_write_to_4(b, (ulint) (n >> 32));
291
mach_write_to_4(b + 4, (ulint) n);
294
/************************************************************
295
The following function is used to fetch data from 8 consecutive
296
bytes. The most significant byte is at the lowest address. */
301
/* out: dulint integer */
302
const byte* b) /* in: pointer to 8 bytes */
309
high = mach_read_from_4(b);
310
low = mach_read_from_4(b + 4);
312
return(ut_dulint_create(high, low));
315
/************************************************************
316
The following function is used to fetch data from 8 consecutive
317
bytes. The most significant byte is at the lowest address. */
322
/* out: 64-bit integer */
323
const byte* b) /* in: pointer to 8 bytes */
327
ull = ((ib_uint64_t) mach_read_from_4(b)) << 32;
328
ull |= (ib_uint64_t) mach_read_from_4(b + 4);
333
/***********************************************************
334
The following function is used to store data in 7 consecutive
335
bytes. We store the most significant byte to the lowest address. */
340
byte* b, /* in: pointer to 7 bytes where to store */
341
dulint n) /* in: dulint integer to be stored */
345
mach_write_to_3(b, ut_dulint_get_high(n));
346
mach_write_to_4(b + 3, ut_dulint_get_low(n));
349
/************************************************************
350
The following function is used to fetch data from 7 consecutive
351
bytes. The most significant byte is at the lowest address. */
356
/* out: dulint integer */
357
const byte* b) /* in: pointer to 7 bytes */
364
high = mach_read_from_3(b);
365
low = mach_read_from_4(b + 3);
367
return(ut_dulint_create(high, low));
370
/***********************************************************
371
The following function is used to store data in 6 consecutive
372
bytes. We store the most significant byte to the lowest address. */
377
byte* b, /* in: pointer to 6 bytes where to store */
378
dulint n) /* in: dulint integer to be stored */
382
mach_write_to_2(b, ut_dulint_get_high(n));
383
mach_write_to_4(b + 2, ut_dulint_get_low(n));
386
/************************************************************
387
The following function is used to fetch data from 6 consecutive
388
bytes. The most significant byte is at the lowest address. */
393
/* out: dulint integer */
394
const byte* b) /* in: pointer to 6 bytes */
401
high = mach_read_from_2(b);
402
low = mach_read_from_4(b + 2);
404
return(ut_dulint_create(high, low));
407
/*************************************************************
408
Writes a dulint in a compressed form (5..9 bytes). */
411
mach_dulint_write_compressed(
412
/*=========================*/
413
/* out: size in bytes */
414
byte* b, /* in: pointer to memory where to store */
415
dulint n) /* in: dulint integer to be stored */
421
size = mach_write_compressed(b, ut_dulint_get_high(n));
422
mach_write_to_4(b + size, ut_dulint_get_low(n));
427
/*************************************************************
428
Returns the size of a dulint when written in the compressed form. */
431
mach_dulint_get_compressed_size(
432
/*============================*/
433
/* out: compressed size in bytes */
434
dulint n) /* in: dulint integer to be stored */
436
return(4 + mach_get_compressed_size(ut_dulint_get_high(n)));
439
/*************************************************************
440
Reads a dulint in a compressed form. */
443
mach_dulint_read_compressed(
444
/*========================*/
445
/* out: read dulint */
446
const byte* b) /* in: pointer to memory from where to read */
454
high = mach_read_compressed(b);
456
size = mach_get_compressed_size(high);
458
low = mach_read_from_4(b + size);
460
return(ut_dulint_create(high, low));
463
/*************************************************************
464
Writes a dulint in a compressed form (1..11 bytes). */
467
mach_dulint_write_much_compressed(
468
/*==============================*/
469
/* out: size in bytes */
470
byte* b, /* in: pointer to memory where to store */
471
dulint n) /* in: dulint integer to be stored */
477
if (ut_dulint_get_high(n) == 0) {
478
return(mach_write_compressed(b, ut_dulint_get_low(n)));
482
size = 1 + mach_write_compressed(b + 1, ut_dulint_get_high(n));
484
size += mach_write_compressed(b + size, ut_dulint_get_low(n));
489
/*************************************************************
490
Returns the size of a dulint when written in the compressed form. */
493
mach_dulint_get_much_compressed_size(
494
/*=================================*/
495
/* out: compressed size in bytes */
496
dulint n) /* in: dulint integer to be stored */
498
if (0 == ut_dulint_get_high(n)) {
499
return(mach_get_compressed_size(ut_dulint_get_low(n)));
502
return(1 + mach_get_compressed_size(ut_dulint_get_high(n))
503
+ mach_get_compressed_size(ut_dulint_get_low(n)));
506
/*************************************************************
507
Reads a dulint in a compressed form. */
510
mach_dulint_read_much_compressed(
511
/*=============================*/
512
/* out: read dulint */
513
const byte* b) /* in: pointer to memory from where to read */
521
if (*b != (byte)0xFF) {
525
high = mach_read_compressed(b + 1);
527
size = 1 + mach_get_compressed_size(high);
530
low = mach_read_compressed(b + size);
532
return(ut_dulint_create(high, low));
535
/*************************************************************
536
Reads a double. It is stored in a little-endian format. */
541
/* out: double read */
542
const byte* b) /* in: pointer to memory from where to read */
550
for (i = 0; i < sizeof(double); i++) {
551
#ifdef WORDS_BIGENDIAN
552
ptr[sizeof(double) - i - 1] = b[i];
561
/*************************************************************
562
Writes a double. It is stored in a little-endian format. */
567
byte* b, /* in: pointer to memory where to write */
568
double d) /* in: double */
575
for (i = 0; i < sizeof(double); i++) {
576
#ifdef WORDS_BIGENDIAN
577
b[i] = ptr[sizeof(double) - i - 1];
584
/*************************************************************
585
Reads a float. It is stored in a little-endian format. */
590
/* out: float read */
591
const byte* b) /* in: pointer to memory from where to read */
599
for (i = 0; i < sizeof(float); i++) {
600
#ifdef WORDS_BIGENDIAN
601
ptr[sizeof(float) - i - 1] = b[i];
610
/*************************************************************
611
Writes a float. It is stored in a little-endian format. */
616
byte* b, /* in: pointer to memory where to write */
617
float d) /* in: float */
624
for (i = 0; i < sizeof(float); i++) {
625
#ifdef WORDS_BIGENDIAN
626
b[i] = ptr[sizeof(float) - i - 1];
633
/*************************************************************
634
Reads a ulint stored in the little-endian format. */
637
mach_read_from_n_little_endian(
638
/*===========================*/
639
/* out: unsigned long int */
640
const byte* buf, /* in: from where to read */
641
ulint buf_size) /* in: from how many bytes to read */
646
ut_ad(buf_size <= sizeof(ulint));
649
ptr = buf + buf_size;
666
/*************************************************************
667
Writes a ulint in the little-endian format. */
670
mach_write_to_n_little_endian(
671
/*==========================*/
672
byte* dest, /* in: where to write */
673
ulint dest_size, /* in: into how many bytes to write */
674
ulint n) /* in: unsigned long int to write */
678
ut_ad(dest_size <= sizeof(ulint));
679
ut_ad(dest_size > 0);
681
end = dest + dest_size;
684
*dest = (byte)(n & 0xFF);
698
/*************************************************************
699
Reads a ulint stored in the little-endian format. */
702
mach_read_from_2_little_endian(
703
/*===========================*/
704
/* out: unsigned long int */
705
const byte* buf) /* in: from where to read */
707
return((ulint)(*buf) + ((ulint)(*(buf + 1))) * 256);
710
/*************************************************************
711
Writes a ulint in the little-endian format. */
714
mach_write_to_2_little_endian(
715
/*==========================*/
716
byte* dest, /* in: where to write */
717
ulint n) /* in: unsigned long int to write */
719
ut_ad(n < 256 * 256);
721
*dest = (byte)(n & 0xFFUL);
726
*dest = (byte)(n & 0xFFUL);
729
/*************************************************************
730
Convert integral type from storage byte order (big endian) to
736
/* out: integer value */
737
const byte* src, /* in: where to read from */
738
ulint len, /* in: length of src */
739
ibool unsigned_type) /* in: signed or unsigned flag */
741
/* XXX this can be optimized on big-endian machines */
746
if (unsigned_type || (src[0] & 0x80)) {
748
ret = 0x0000000000000000ULL;
751
ret = 0xFFFFFFFFFFFFFF00ULL;
759
ret |= src[0] ^ 0x80;
762
for (i = 1; i < len; i++) {