1/***************************************************************************** 2 3Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved. 4Copyright (c) 2017, 2020, 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/*********************************************************//** 550Reads a double. It is stored in a little-endian format. 551@return double read */ 552UNIV_INLINE 553double 554mach_double_read( 555/*=============*/ 556 const byte* b) /*!< in: pointer to memory from where to read */ 557{ 558 double d; 559 ulint i; 560 byte* ptr; 561 562 ptr = (byte*) &d; 563 564 for (i = 0; i < sizeof(double); i++) { 565#ifdef WORDS_BIGENDIAN 566 ptr[sizeof(double) - i - 1] = b[i]; 567#else 568 ptr[i] = b[i]; 569#endif 570 } 571 572 return(d); 573} 574 575/*********************************************************//** 576Writes a double. It is stored in a little-endian format. */ 577UNIV_INLINE 578void 579mach_double_write( 580/*==============*/ 581 byte* b, /*!< in: pointer to memory where to write */ 582 double d) /*!< in: double */ 583{ 584 ulint i; 585 byte* ptr; 586 587 ptr = (byte*) &d; 588 589 for (i = 0; i < sizeof(double); i++) { 590#ifdef WORDS_BIGENDIAN 591 b[i] = ptr[sizeof(double) - i - 1]; 592#else 593 b[i] = ptr[i]; 594#endif 595 } 596} 597 598/*********************************************************//** 599Reads a float. It is stored in a little-endian format. 600@return float read */ 601UNIV_INLINE 602float 603mach_float_read( 604/*============*/ 605 const byte* b) /*!< in: pointer to memory from where to read */ 606{ 607 float d; 608 ulint i; 609 byte* ptr; 610 611 ptr = (byte*) &d; 612 613 for (i = 0; i < sizeof(float); i++) { 614#ifdef WORDS_BIGENDIAN 615 ptr[sizeof(float) - i - 1] = b[i]; 616#else 617 ptr[i] = b[i]; 618#endif 619 } 620 621 return(d); 622} 623 624/*********************************************************//** 625Writes a float. It is stored in a little-endian format. */ 626UNIV_INLINE 627void 628mach_float_write( 629/*=============*/ 630 byte* b, /*!< in: pointer to memory where to write */ 631 float d) /*!< in: float */ 632{ 633 ulint i; 634 byte* ptr; 635 636 ptr = (byte*) &d; 637 638 for (i = 0; i < sizeof(float); i++) { 639#ifdef WORDS_BIGENDIAN 640 b[i] = ptr[sizeof(float) - i - 1]; 641#else 642 b[i] = ptr[i]; 643#endif 644 } 645} 646 647/*********************************************************//** 648Reads a ulint stored in the little-endian format. 649@return unsigned long int */ 650UNIV_INLINE 651ulint 652mach_read_from_n_little_endian( 653/*===========================*/ 654 const byte* buf, /*!< in: from where to read */ 655 ulint buf_size) /*!< in: from how many bytes to read */ 656{ 657 ulint n = 0; 658 const byte* ptr; 659 660 ut_ad(buf_size > 0); 661 662 ptr = buf + buf_size; 663 664 for (;;) { 665 ptr--; 666 667 n = n << 8; 668 669 n += (ulint)(*ptr); 670 671 if (ptr == buf) { 672 break; 673 } 674 } 675 676 return(n); 677} 678 679/*********************************************************//** 680Writes a ulint in the little-endian format. */ 681UNIV_INLINE 682void 683mach_write_to_n_little_endian( 684/*==========================*/ 685 byte* dest, /*!< in: where to write */ 686 ulint dest_size, /*!< in: into how many bytes to write */ 687 ulint n) /*!< in: unsigned long int to write */ 688{ 689 byte* end; 690 691 ut_ad(dest_size <= sizeof(ulint)); 692 ut_ad(dest_size > 0); 693 694 end = dest + dest_size; 695 696 for (;;) { 697 *dest = (byte)(n & 0xFF); 698 699 n = n >> 8; 700 701 dest++; 702 703 if (dest == end) { 704 break; 705 } 706 } 707 708 ut_ad(n == 0); 709} 710 711/*********************************************************//** 712Reads a ulint stored in the little-endian format. 713@return unsigned long int */ 714UNIV_INLINE 715ulint 716mach_read_from_2_little_endian( 717/*===========================*/ 718 const byte* buf) /*!< in: from where to read */ 719{ 720 return((ulint)(buf[0]) | ((ulint)(buf[1]) << 8)); 721} 722 723/*********************************************************//** 724Writes a ulint in the little-endian format. */ 725UNIV_INLINE 726void 727mach_write_to_2_little_endian( 728/*==========================*/ 729 byte* dest, /*!< in: where to write */ 730 ulint n) /*!< in: unsigned long int to write */ 731{ 732 ut_ad(n < 256 * 256); 733 734 *dest = (byte)(n & 0xFFUL); 735 736 n = n >> 8; 737 dest++; 738 739 *dest = (byte)(n & 0xFFUL); 740} 741 742/*********************************************************//** 743Convert integral type from storage byte order (big endian) to 744host byte order. 745@return integer value */ 746UNIV_INLINE 747ib_uint64_t 748mach_read_int_type( 749/*===============*/ 750 const byte* src, /*!< in: where to read from */ 751 ulint len, /*!< in: length of src */ 752 ibool unsigned_type) /*!< in: signed or unsigned flag */ 753{ 754 /* XXX this can be optimized on big-endian machines */ 755 756 uintmax_t ret; 757 uint i; 758 759 if (unsigned_type || (src[0] & 0x80)) { 760 761 ret = 0x0000000000000000ULL; 762 } else { 763 764 ret = 0xFFFFFFFFFFFFFF00ULL; 765 } 766 767 if (unsigned_type) { 768 769 ret |= src[0]; 770 } else { 771 772 ret |= src[0] ^ 0x80; 773 } 774 775 for (i = 1; i < len; i++) { 776 ret <<= 8; 777 ret |= src[i]; 778 } 779 780 return(ret); 781} 782/*********************************************************//** 783Swap byte ordering. */ 784UNIV_INLINE 785void 786mach_swap_byte_order( 787/*=================*/ 788 byte* dest, /*!< out: where to write */ 789 const byte* from, /*!< in: where to read from */ 790 ulint len) /*!< in: length of src */ 791{ 792 ut_ad(len > 0); 793 ut_ad(len <= 8); 794 795 dest += len; 796 797 switch (len & 0x7) { 798 case 0: *--dest = *from++; /* fall through */ 799 case 7: *--dest = *from++; /* fall through */ 800 case 6: *--dest = *from++; /* fall through */ 801 case 5: *--dest = *from++; /* fall through */ 802 case 4: *--dest = *from++; /* fall through */ 803 case 3: *--dest = *from++; /* fall through */ 804 case 2: *--dest = *from++; /* fall through */ 805 case 1: *--dest = *from; 806 } 807} 808 809/************************************************************* 810Convert a ulonglong integer from host byte order to (big-endian) 811storage byte order. */ 812UNIV_INLINE 813void 814mach_write_ulonglong( 815/*=================*/ 816 byte* dest, /*!< in: where to write */ 817 ulonglong src, /*!< in: where to read from */ 818 ulint len, /*!< in: length of dest */ 819 bool usign) /*!< in: signed or unsigned flag */ 820{ 821 byte* ptr = reinterpret_cast<byte*>(&src); 822 823 ut_ad(len <= sizeof(ulonglong)); 824 825#ifdef WORDS_BIGENDIAN 826 memcpy(dest, ptr + (sizeof(src) - len), len); 827#else 828 mach_swap_byte_order(dest, reinterpret_cast<byte*>(ptr), len); 829#endif /* WORDS_BIGENDIAN */ 830 831 if (!usign) { 832 *dest ^= 0x80; 833 } 834} 835 836#endif /* !UNIV_INNOCHECKSUM */ 837