1/***************************************************************************** 2 3Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved. 4Copyright (c) 2017, MariaDB Corporation. 5 6This program is free software; you can redistribute it and/or modify it under 7the terms of the GNU General Public License as published by the Free Software 8Foundation; version 2 of the License. 9 10This program is distributed in the hope that it will be useful, but WITHOUT 11ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 13 14You should have received a copy of the GNU General Public License along with 15this program; if not, write to the Free Software Foundation, Inc., 1651 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA 17 18*****************************************************************************/ 19 20/******************************************************************//** 21@file include/mach0data.ic 22Utilities for converting data from the database file 23to the machine format. 24 25Created 11/28/1995 Heikki Tuuri 26***********************************************************************/ 27 28#ifndef UNIV_INNOCHECKSUM 29 30#include "mtr0types.h" 31 32/*******************************************************//** 33The following function is used to store data in one byte. */ 34UNIV_INLINE 35void 36mach_write_to_1( 37/*============*/ 38 byte* b, /*!< in: pointer to byte where to store */ 39 ulint n) /*!< in: ulint integer to be stored, >= 0, < 256 */ 40{ 41 ut_ad((n & ~0xFFUL) == 0); 42 43 b[0] = (byte) n; 44} 45 46#endif /* !UNIV_INNOCHECKSUM */ 47 48/*******************************************************//** 49The following function is used to store data in two consecutive 50bytes. We store the most significant byte to the lowest address. */ 51UNIV_INLINE 52void 53mach_write_to_2( 54/*============*/ 55 byte* b, /*!< in: pointer to two bytes where to store */ 56 ulint n) /*!< in: ulint integer to be stored */ 57{ 58 ut_ad((n & ~0xFFFFUL) == 0); 59 60 b[0] = (byte)(n >> 8); 61 b[1] = (byte)(n); 62} 63 64/** The following function is used to fetch data from one byte. 65@param[in] b pointer to a byte to read 66@return ulint integer, >= 0, < 256 */ 67UNIV_INLINE 68uint8_t 69mach_read_from_1( 70 const byte* b) 71{ 72 return(uint8_t(*b)); 73} 74 75/** The following function is used to fetch data from 2 consecutive 76bytes. The most significant byte is at the lowest address. 77@param[in] b pointer to 2 bytes to read 78@return 2-byte integer, >= 0, < 64k */ 79UNIV_INLINE 80uint16_t 81mach_read_from_2( 82 const byte* b) 83{ 84 return(uint16_t(uint16_t(b[0]) << 8 | b[1])); 85} 86 87#ifndef UNIV_INNOCHECKSUM 88 89/********************************************************//** 90The following function is used to convert a 16-bit data item 91to the canonical format, for fast bytewise equality test 92against memory. 93@return 16-bit integer in canonical format */ 94UNIV_INLINE 95uint16 96mach_encode_2( 97/*==========*/ 98 ulint n) /*!< in: integer in machine-dependent format */ 99{ 100 uint16 ret; 101 ut_ad(2 == sizeof ret); 102 mach_write_to_2((byte*) &ret, n); 103 return(ret); 104} 105/********************************************************//** 106The following function is used to convert a 16-bit data item 107from the canonical format, for fast bytewise equality test 108against memory. 109@return integer in machine-dependent format */ 110UNIV_INLINE 111ulint 112mach_decode_2( 113/*==========*/ 114 uint16 n) /*!< in: 16-bit integer in canonical format */ 115{ 116 ut_ad(2 == sizeof n); 117 return(mach_read_from_2((const byte*) &n)); 118} 119 120/*******************************************************//** 121The following function is used to store data in 3 consecutive 122bytes. We store the most significant byte to the lowest address. */ 123UNIV_INLINE 124void 125mach_write_to_3( 126/*============*/ 127 byte* b, /*!< in: pointer to 3 bytes where to store */ 128 ulint n) /*!< in: ulint integer to be stored */ 129{ 130 ut_ad((n & ~0xFFFFFFUL) == 0); 131 132 b[0] = (byte)(n >> 16); 133 b[1] = (byte)(n >> 8); 134 b[2] = (byte)(n); 135} 136 137/** The following function is used to fetch data from 3 consecutive 138bytes. The most significant byte is at the lowest address. 139@param[in] b pointer to 3 bytes to read 140@return uint32_t integer */ 141UNIV_INLINE 142uint32_t 143mach_read_from_3( 144 const byte* b) 145{ 146 return( (static_cast<uint32_t>(b[0]) << 16) 147 | (static_cast<uint32_t>(b[1]) << 8) 148 | static_cast<uint32_t>(b[2]) 149 ); 150} 151#endif /* !UNIV_INNOCHECKSUM */ 152 153/*******************************************************//** 154The following function is used to store data in four consecutive 155bytes. We store the most significant byte to the lowest address. */ 156UNIV_INLINE 157void 158mach_write_to_4( 159/*============*/ 160 byte* b, /*!< in: pointer to four bytes where to store */ 161 ulint n) /*!< in: ulint integer to be stored */ 162{ 163 b[0] = (byte)(n >> 24); 164 b[1] = (byte)(n >> 16); 165 b[2] = (byte)(n >> 8); 166 b[3] = (byte) n; 167} 168 169/** The following function is used to fetch data from 4 consecutive 170bytes. The most significant byte is at the lowest address. 171@param[in] b pointer to 4 bytes to read 172@return 32 bit integer */ 173UNIV_INLINE 174uint32_t 175mach_read_from_4( 176 const byte* b) 177{ 178 return( (static_cast<uint32_t>(b[0]) << 24) 179 | (static_cast<uint32_t>(b[1]) << 16) 180 | (static_cast<uint32_t>(b[2]) << 8) 181 | static_cast<uint32_t>(b[3]) 182 ); 183} 184 185#ifndef UNIV_INNOCHECKSUM 186 187/*********************************************************//** 188Writes a ulint in a compressed form where the first byte codes the 189length of the stored ulint. We look at the most significant bits of 190the byte. If the most significant bit is zero, it means 1-byte storage, 191else if the 2nd bit is 0, it means 2-byte storage, else if 3rd is 0, 192it means 3-byte storage, else if 4th is 0, it means 4-byte storage, 193else the storage is 5-byte. 194@return compressed size in bytes */ 195UNIV_INLINE 196ulint 197mach_write_compressed( 198/*==================*/ 199 byte* b, /*!< in: pointer to memory where to store */ 200 ulint n) /*!< in: ulint integer (< 2^32) to be stored */ 201{ 202 if (n < 0x80) { 203 /* 0nnnnnnn (7 bits) */ 204 mach_write_to_1(b, n); 205 return(1); 206 } else if (n < 0x4000) { 207 /* 10nnnnnn nnnnnnnn (14 bits) */ 208 mach_write_to_2(b, n | 0x8000); 209 return(2); 210 } else if (n < 0x200000) { 211 /* 110nnnnn nnnnnnnn nnnnnnnn (21 bits) */ 212 mach_write_to_3(b, n | 0xC00000); 213 return(3); 214 } else if (n < 0x10000000) { 215 /* 1110nnnn nnnnnnnn nnnnnnnn nnnnnnnn (28 bits) */ 216 mach_write_to_4(b, n | 0xE0000000); 217 return(4); 218 } else { 219 /* 11110000 nnnnnnnn nnnnnnnn nnnnnnnn nnnnnnnn (32 bits) */ 220 mach_write_to_1(b, 0xF0); 221 mach_write_to_4(b + 1, n); 222 return(5); 223 } 224} 225 226/*********************************************************//** 227Returns the size of a ulint when written in the compressed form. 228@return compressed size in bytes */ 229UNIV_INLINE 230ulint 231mach_get_compressed_size( 232/*=====================*/ 233 ulint n) /*!< in: ulint integer (< 2^32) to be stored */ 234{ 235 if (n < 0x80) { 236 /* 0nnnnnnn (7 bits) */ 237 return(1); 238 } else if (n < 0x4000) { 239 /* 10nnnnnn nnnnnnnn (14 bits) */ 240 return(2); 241 } else if (n < 0x200000) { 242 /* 110nnnnn nnnnnnnn nnnnnnnn (21 bits) */ 243 return(3); 244 } else if (n < 0x10000000) { 245 /* 1110nnnn nnnnnnnn nnnnnnnn nnnnnnnn (28 bits) */ 246 return(4); 247 } else { 248 /* 11110000 nnnnnnnn nnnnnnnn nnnnnnnn nnnnnnnn (32 bits) */ 249 return(5); 250 } 251} 252 253/*********************************************************//** 254Reads a ulint in a compressed form. 255@return read integer (< 2^32) */ 256UNIV_INLINE 257ulint 258mach_read_compressed( 259/*=================*/ 260 const byte* b) /*!< in: pointer to memory from where to read */ 261{ 262 ulint val; 263 264 val = mach_read_from_1(b); 265 266 if (val < 0x80) { 267 /* 0nnnnnnn (7 bits) */ 268 } else if (val < 0xC0) { 269 /* 10nnnnnn nnnnnnnn (14 bits) */ 270 val = mach_read_from_2(b) & 0x3FFF; 271 ut_ad(val > 0x7F); 272 } else if (val < 0xE0) { 273 /* 110nnnnn nnnnnnnn nnnnnnnn (21 bits) */ 274 val = mach_read_from_3(b) & 0x1FFFFF; 275 ut_ad(val > 0x3FFF); 276 } else if (val < 0xF0) { 277 /* 1110nnnn nnnnnnnn nnnnnnnn nnnnnnnn (28 bits) */ 278 val = mach_read_from_4(b) & 0xFFFFFFF; 279 ut_ad(val > 0x1FFFFF); 280 } else { 281 /* 11110000 nnnnnnnn nnnnnnnn nnnnnnnn nnnnnnnn (32 bits) */ 282 ut_ad(val == 0xF0); 283 val = mach_read_from_4(b + 1); 284 ut_ad(val > 0xFFFFFFF); 285 } 286 287 return(val); 288} 289 290/** Read a 32-bit integer in a compressed form. 291@param[in,out] b pointer to memory where to read; 292advanced by the number of bytes consumed 293@return unsigned value */ 294UNIV_INLINE 295ib_uint32_t 296mach_read_next_compressed( 297 const byte** b) 298{ 299 ulint val = mach_read_from_1(*b); 300 301 if (val < 0x80) { 302 /* 0nnnnnnn (7 bits) */ 303 ++*b; 304 } else if (val < 0xC0) { 305 /* 10nnnnnn nnnnnnnn (14 bits) */ 306 val = mach_read_from_2(*b) & 0x3FFF; 307 ut_ad(val > 0x7F); 308 *b += 2; 309 } else if (val < 0xE0) { 310 /* 110nnnnn nnnnnnnn nnnnnnnn (21 bits) */ 311 val = mach_read_from_3(*b) & 0x1FFFFF; 312 ut_ad(val > 0x3FFF); 313 *b += 3; 314 } else if (val < 0xF0) { 315 /* 1110nnnn nnnnnnnn nnnnnnnn nnnnnnnn (28 bits) */ 316 val = mach_read_from_4(*b) & 0xFFFFFFF; 317 ut_ad(val > 0x1FFFFF); 318 *b += 4; 319 } else { 320 /* 11110000 nnnnnnnn nnnnnnnn nnnnnnnn nnnnnnnn (32 bits) */ 321 ut_ad(val == 0xF0); 322 val = mach_read_from_4(*b + 1); 323 ut_ad(val > 0xFFFFFFF); 324 *b += 5; 325 } 326 327 return(static_cast<ib_uint32_t>(val)); 328} 329 330/*******************************************************//** 331The following function is used to store data in 8 consecutive 332bytes. We store the most significant byte to the lowest address. */ 333UNIV_INLINE 334void 335mach_write_to_8( 336/*============*/ 337 void* b, /*!< in: pointer to 8 bytes where to store */ 338 ib_uint64_t n) /*!< in: 64-bit integer to be stored */ 339{ 340 mach_write_to_4(static_cast<byte*>(b), (ulint) (n >> 32)); 341 mach_write_to_4(static_cast<byte*>(b) + 4, (ulint) n); 342} 343 344#endif /* !UNIV_INNOCHECKSUM */ 345 346/********************************************************//** 347The following function is used to fetch data from 8 consecutive 348bytes. The most significant byte is at the lowest address. 349@return 64-bit integer */ 350UNIV_INLINE 351ib_uint64_t 352mach_read_from_8( 353/*=============*/ 354 const byte* b) /*!< in: pointer to 8 bytes */ 355{ 356 ib_uint64_t u64; 357 358 u64 = mach_read_from_4(b); 359 u64 <<= 32; 360 u64 |= mach_read_from_4(b + 4); 361 362 return(u64); 363} 364 365#ifndef UNIV_INNOCHECKSUM 366 367/*******************************************************//** 368The following function is used to store data in 7 consecutive 369bytes. We store the most significant byte to the lowest address. */ 370UNIV_INLINE 371void 372mach_write_to_7( 373/*============*/ 374 byte* b, /*!< in: pointer to 7 bytes where to store */ 375 ib_uint64_t n) /*!< in: 56-bit integer */ 376{ 377 mach_write_to_3(b, (ulint) (n >> 32)); 378 mach_write_to_4(b + 3, (ulint) n); 379} 380 381/********************************************************//** 382The following function is used to fetch data from 7 consecutive 383bytes. The most significant byte is at the lowest address. 384@return 56-bit integer */ 385UNIV_INLINE 386ib_uint64_t 387mach_read_from_7( 388/*=============*/ 389 const byte* b) /*!< in: pointer to 7 bytes */ 390{ 391 return(ut_ull_create(mach_read_from_3(b), mach_read_from_4(b + 3))); 392} 393 394/*******************************************************//** 395The following function is used to store data in 6 consecutive 396bytes. We store the most significant byte to the lowest address. */ 397UNIV_INLINE 398void 399mach_write_to_6( 400/*============*/ 401 byte* b, /*!< in: pointer to 6 bytes where to store */ 402 ib_uint64_t n) /*!< in: 48-bit integer */ 403{ 404 mach_write_to_2(b, (ulint) (n >> 32)); 405 mach_write_to_4(b + 2, (ulint) n); 406} 407 408/********************************************************//** 409The following function is used to fetch data from 6 consecutive 410bytes. The most significant byte is at the lowest address. 411@return 48-bit integer */ 412UNIV_INLINE 413ib_uint64_t 414mach_read_from_6( 415/*=============*/ 416 const byte* b) /*!< in: pointer to 6 bytes */ 417{ 418 return(ut_ull_create(mach_read_from_2(b), mach_read_from_4(b + 2))); 419} 420 421/*********************************************************//** 422Writes a 64-bit integer in a compressed form (5..9 bytes). 423@return size in bytes */ 424UNIV_INLINE 425ulint 426mach_u64_write_compressed( 427/*======================*/ 428 byte* b, /*!< in: pointer to memory where to store */ 429 ib_uint64_t n) /*!< in: 64-bit integer to be stored */ 430{ 431 ulint size = mach_write_compressed(b, (ulint) (n >> 32)); 432 mach_write_to_4(b + size, (ulint) n); 433 434 return(size + 4); 435} 436 437/** Read a 64-bit integer in a compressed form. 438@param[in,out] b pointer to memory where to read; 439advanced by the number of bytes consumed 440@return unsigned value */ 441UNIV_INLINE 442ib_uint64_t 443mach_u64_read_next_compressed( 444 const byte** b) 445{ 446 ib_uint64_t val; 447 448 val = mach_read_next_compressed(b); 449 val <<= 32; 450 val |= mach_read_from_4(*b); 451 *b += 4; 452 return(val); 453} 454 455/*********************************************************//** 456Writes a 64-bit integer in a compressed form (1..11 bytes). 457@return size in bytes */ 458UNIV_INLINE 459ulint 460mach_u64_write_much_compressed( 461/*===========================*/ 462 byte* b, /*!< in: pointer to memory where to store */ 463 ib_uint64_t n) /*!< in: 64-bit integer to be stored */ 464{ 465 ulint size; 466 467 if (!(n >> 32)) { 468 return(mach_write_compressed(b, (ulint) n)); 469 } 470 471 *b = (byte)0xFF; 472 size = 1 + mach_write_compressed(b + 1, (ulint) (n >> 32)); 473 474 size += mach_write_compressed(b + size, (ulint) n & 0xFFFFFFFF); 475 476 return(size); 477} 478 479/*********************************************************//** 480Reads a 64-bit integer in a compressed form. 481@return the value read */ 482UNIV_INLINE 483ib_uint64_t 484mach_u64_read_much_compressed( 485/*==========================*/ 486 const byte* b) /*!< in: pointer to memory from where to read */ 487{ 488 ib_uint64_t n; 489 490 if (*b != 0xFF) { 491 return(mach_read_compressed(b)); 492 } 493 494 b++; 495 n = mach_read_next_compressed(&b); 496 n <<= 32; 497 n |= mach_read_compressed(b); 498 499 return(n); 500} 501 502/** Read a 64-bit integer in a compressed form. 503@param[in,out] b pointer to memory where to read; 504advanced by the number of bytes consumed 505@return unsigned value */ 506UNIV_INLINE 507ib_uint64_t 508mach_read_next_much_compressed( 509 const byte** b) 510{ 511 ib_uint64_t val = mach_read_from_1(*b); 512 513 if (val < 0x80) { 514 /* 0nnnnnnn (7 bits) */ 515 ++*b; 516 } else if (val < 0xC0) { 517 /* 10nnnnnn nnnnnnnn (14 bits) */ 518 val = mach_read_from_2(*b) & 0x3FFF; 519 ut_ad(val > 0x7F); 520 *b += 2; 521 } else if (val < 0xE0) { 522 /* 110nnnnn nnnnnnnn nnnnnnnn (21 bits) */ 523 val = mach_read_from_3(*b) & 0x1FFFFF; 524 ut_ad(val > 0x3FFF); 525 *b += 3; 526 } else if (val < 0xF0) { 527 /* 1110nnnn nnnnnnnn nnnnnnnn nnnnnnnn (28 bits) */ 528 val = mach_read_from_4(*b) & 0xFFFFFFF; 529 ut_ad(val > 0x1FFFFF); 530 *b += 4; 531 } else if (val == 0xF0) { 532 /* 11110000 nnnnnnnn nnnnnnnn nnnnnnnn nnnnnnnn (32 bits) */ 533 val = mach_read_from_4(*b + 1); 534 ut_ad(val > 0xFFFFFFF); 535 *b += 5; 536 } else { 537 /* 11111111 followed by up to 64 bits */ 538 ut_ad(val == 0xFF); 539 ++*b; 540 val = mach_read_next_compressed(b); 541 ut_ad(val > 0); 542 val <<= 32; 543 val |= mach_read_next_compressed(b); 544 } 545 546 return(val); 547} 548 549/** Read a 64-bit integer in a compressed form. 550@param[in,out] ptr pointer to memory where to read; 551advanced by the number of bytes consumed, or set NULL if out of space 552@param[in] end_ptr end of the buffer 553@return unsigned value */ 554UNIV_INLINE 555ib_uint64_t 556mach_u64_parse_compressed( 557 const byte** ptr, 558 const byte* end_ptr) 559{ 560 ib_uint64_t val = 0; 561 562 if (end_ptr < *ptr + 5) { 563 *ptr = NULL; 564 return(val); 565 } 566 567 val = mach_read_next_compressed(ptr); 568 569 if (end_ptr < *ptr + 4) { 570 *ptr = NULL; 571 return(val); 572 } 573 574 val <<= 32; 575 val |= mach_read_from_4(*ptr); 576 *ptr += 4; 577 578 return(val); 579} 580 581/*********************************************************//** 582Reads a double. It is stored in a little-endian format. 583@return double read */ 584UNIV_INLINE 585double 586mach_double_read( 587/*=============*/ 588 const byte* b) /*!< in: pointer to memory from where to read */ 589{ 590 double d; 591 ulint i; 592 byte* ptr; 593 594 ptr = (byte*) &d; 595 596 for (i = 0; i < sizeof(double); i++) { 597#ifdef WORDS_BIGENDIAN 598 ptr[sizeof(double) - i - 1] = b[i]; 599#else 600 ptr[i] = b[i]; 601#endif 602 } 603 604 return(d); 605} 606 607/*********************************************************//** 608Writes a double. It is stored in a little-endian format. */ 609UNIV_INLINE 610void 611mach_double_write( 612/*==============*/ 613 byte* b, /*!< in: pointer to memory where to write */ 614 double d) /*!< in: double */ 615{ 616 ulint i; 617 byte* ptr; 618 619 ptr = (byte*) &d; 620 621 for (i = 0; i < sizeof(double); i++) { 622#ifdef WORDS_BIGENDIAN 623 b[i] = ptr[sizeof(double) - i - 1]; 624#else 625 b[i] = ptr[i]; 626#endif 627 } 628} 629 630/*********************************************************//** 631Reads a float. It is stored in a little-endian format. 632@return float read */ 633UNIV_INLINE 634float 635mach_float_read( 636/*============*/ 637 const byte* b) /*!< in: pointer to memory from where to read */ 638{ 639 float d; 640 ulint i; 641 byte* ptr; 642 643 ptr = (byte*) &d; 644 645 for (i = 0; i < sizeof(float); i++) { 646#ifdef WORDS_BIGENDIAN 647 ptr[sizeof(float) - i - 1] = b[i]; 648#else 649 ptr[i] = b[i]; 650#endif 651 } 652 653 return(d); 654} 655 656/*********************************************************//** 657Writes a float. It is stored in a little-endian format. */ 658UNIV_INLINE 659void 660mach_float_write( 661/*=============*/ 662 byte* b, /*!< in: pointer to memory where to write */ 663 float d) /*!< in: float */ 664{ 665 ulint i; 666 byte* ptr; 667 668 ptr = (byte*) &d; 669 670 for (i = 0; i < sizeof(float); i++) { 671#ifdef WORDS_BIGENDIAN 672 b[i] = ptr[sizeof(float) - i - 1]; 673#else 674 b[i] = ptr[i]; 675#endif 676 } 677} 678 679/*********************************************************//** 680Reads a ulint stored in the little-endian format. 681@return unsigned long int */ 682UNIV_INLINE 683ulint 684mach_read_from_n_little_endian( 685/*===========================*/ 686 const byte* buf, /*!< in: from where to read */ 687 ulint buf_size) /*!< in: from how many bytes to read */ 688{ 689 ulint n = 0; 690 const byte* ptr; 691 692 ut_ad(buf_size > 0); 693 694 ptr = buf + buf_size; 695 696 for (;;) { 697 ptr--; 698 699 n = n << 8; 700 701 n += (ulint)(*ptr); 702 703 if (ptr == buf) { 704 break; 705 } 706 } 707 708 return(n); 709} 710 711/*********************************************************//** 712Writes a ulint in the little-endian format. */ 713UNIV_INLINE 714void 715mach_write_to_n_little_endian( 716/*==========================*/ 717 byte* dest, /*!< in: where to write */ 718 ulint dest_size, /*!< in: into how many bytes to write */ 719 ulint n) /*!< in: unsigned long int to write */ 720{ 721 byte* end; 722 723 ut_ad(dest_size <= sizeof(ulint)); 724 ut_ad(dest_size > 0); 725 726 end = dest + dest_size; 727 728 for (;;) { 729 *dest = (byte)(n & 0xFF); 730 731 n = n >> 8; 732 733 dest++; 734 735 if (dest == end) { 736 break; 737 } 738 } 739 740 ut_ad(n == 0); 741} 742 743/*********************************************************//** 744Reads a ulint stored in the little-endian format. 745@return unsigned long int */ 746UNIV_INLINE 747ulint 748mach_read_from_2_little_endian( 749/*===========================*/ 750 const byte* buf) /*!< in: from where to read */ 751{ 752 return((ulint)(buf[0]) | ((ulint)(buf[1]) << 8)); 753} 754 755/*********************************************************//** 756Writes a ulint in the little-endian format. */ 757UNIV_INLINE 758void 759mach_write_to_2_little_endian( 760/*==========================*/ 761 byte* dest, /*!< in: where to write */ 762 ulint n) /*!< in: unsigned long int to write */ 763{ 764 ut_ad(n < 256 * 256); 765 766 *dest = (byte)(n & 0xFFUL); 767 768 n = n >> 8; 769 dest++; 770 771 *dest = (byte)(n & 0xFFUL); 772} 773 774/*********************************************************//** 775Convert integral type from storage byte order (big endian) to 776host byte order. 777@return integer value */ 778UNIV_INLINE 779ib_uint64_t 780mach_read_int_type( 781/*===============*/ 782 const byte* src, /*!< in: where to read from */ 783 ulint len, /*!< in: length of src */ 784 ibool unsigned_type) /*!< in: signed or unsigned flag */ 785{ 786 /* XXX this can be optimized on big-endian machines */ 787 788 uintmax_t ret; 789 uint i; 790 791 if (unsigned_type || (src[0] & 0x80)) { 792 793 ret = 0x0000000000000000ULL; 794 } else { 795 796 ret = 0xFFFFFFFFFFFFFF00ULL; 797 } 798 799 if (unsigned_type) { 800 801 ret |= src[0]; 802 } else { 803 804 ret |= src[0] ^ 0x80; 805 } 806 807 for (i = 1; i < len; i++) { 808 ret <<= 8; 809 ret |= src[i]; 810 } 811 812 return(ret); 813} 814/*********************************************************//** 815Swap byte ordering. */ 816UNIV_INLINE 817void 818mach_swap_byte_order( 819/*=================*/ 820 byte* dest, /*!< out: where to write */ 821 const byte* from, /*!< in: where to read from */ 822 ulint len) /*!< in: length of src */ 823{ 824 ut_ad(len > 0); 825 ut_ad(len <= 8); 826 827 dest += len; 828 829 switch (len & 0x7) { 830 case 0: *--dest = *from++; /* fall through */ 831 case 7: *--dest = *from++; /* fall through */ 832 case 6: *--dest = *from++; /* fall through */ 833 case 5: *--dest = *from++; /* fall through */ 834 case 4: *--dest = *from++; /* fall through */ 835 case 3: *--dest = *from++; /* fall through */ 836 case 2: *--dest = *from++; /* fall through */ 837 case 1: *--dest = *from; 838 } 839} 840 841/************************************************************* 842Convert a ulonglong integer from host byte order to (big-endian) 843storage byte order. */ 844UNIV_INLINE 845void 846mach_write_ulonglong( 847/*=================*/ 848 byte* dest, /*!< in: where to write */ 849 ulonglong src, /*!< in: where to read from */ 850 ulint len, /*!< in: length of dest */ 851 bool usign) /*!< in: signed or unsigned flag */ 852{ 853 byte* ptr = reinterpret_cast<byte*>(&src); 854 855 ut_ad(len <= sizeof(ulonglong)); 856 857#ifdef WORDS_BIGENDIAN 858 memcpy(dest, ptr + (sizeof(src) - len), len); 859#else 860 mach_swap_byte_order(dest, reinterpret_cast<byte*>(ptr), len); 861#endif /* WORDS_BIGENDIAN */ 862 863 if (!usign) { 864 *dest ^= 0x80; 865 } 866} 867 868#endif /* !UNIV_INNOCHECKSUM */ 869 870/** Read 1 to 4 bytes from a file page buffered in the buffer pool. 871@param[in] ptr pointer where to read 872@param[in] type MLOG_1BYTE, MLOG_2BYTES, or MLOG_4BYTES 873@return value read */ 874UNIV_INLINE 875ulint 876mach_read_ulint( 877 const byte* ptr, 878 mlog_id_t type) 879{ 880 switch (type) { 881 case MLOG_1BYTE: 882 return(mach_read_from_1(ptr)); 883 case MLOG_2BYTES: 884 return(mach_read_from_2(ptr)); 885 case MLOG_4BYTES: 886 return(mach_read_from_4(ptr)); 887 default: 888 break; 889 } 890 891 ut_error; 892 return(0); 893} 894