1/***************************************************************************** 2 3Copyright (c) 1995, 2020, Oracle and/or its affiliates. All Rights Reserved. 4 5This program is free software; you can redistribute it and/or modify it under 6the terms of the GNU General Public License, version 2.0, as published by the 7Free Software Foundation. 8 9This program is also distributed with certain software (including but not 10limited to OpenSSL) that is licensed under separate terms, as designated in a 11particular file or component or in included license documentation. The authors 12of MySQL hereby grant you an additional permission to link the program and 13your derivative works with the separately licensed software that they have 14included with MySQL. 15 16This program is distributed in the hope that it will be useful, but WITHOUT 17ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 18FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0, 19for more details. 20 21You should have received a copy of the GNU General Public License along with 22this program; if not, write to the Free Software Foundation, Inc., 2351 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 25*****************************************************************************/ 26 27/** @file include/mach0data.ic 28 Utilities for converting data from the database file 29 to the machine format. 30 31 Created 11/28/1995 Heikki Tuuri 32 ***********************************************************************/ 33 34#include "mtr0types.h" 35#include "ut0byte.h" 36#include "log0types.h" 37 38extern uint32_t log_detected_format; 39 40/** The following function is used to store data in one byte. 41@param[in] b pointer to byte where to store 42@param[in] n ulint integer to be stored, >= 0, < 256 */ 43UNIV_INLINE 44void mach_write_to_1(byte *b, ulint n) { 45 ut_ad(b); 46 ut_ad((n | 0xFFUL) <= 0xFFUL); 47 48 b[0] = (byte)n; 49} 50 51/** The following function is used to store data in two consecutive 52bytes. We store the most significant byte to the lower address. 53@param[in] b pointer to 2 bytes where to store 54@param[in] n 2 byte integer to be stored, >= 0, < 64k */ 55UNIV_INLINE 56void mach_write_to_2(byte *b, ulint n) { 57 ut_ad(b); 58 ut_ad((n | 0xFFFFUL) <= 0xFFFFUL); 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 mach_read_from_1(const byte *b) { 69 ut_ad(b); 70 return ((uint8_t)(b[0])); 71} 72 73/** The following function is used to fetch data from 2 consecutive 74bytes. The most significant byte is at the lowest address. 75@param[in] b pointer to 2 bytes to read 76@return 2-byte integer, >= 0, < 64k */ 77UNIV_INLINE 78uint16_t mach_read_from_2(const byte *b) { 79 return (((ulint)(b[0]) << 8) | (ulint)(b[1])); 80} 81 82/** The following function is used to convert a 16-bit data item 83 to the canonical format, for fast bytewise equality test 84 against memory. 85 @return 16-bit integer in canonical format */ 86UNIV_INLINE 87uint16_t mach_encode_2(ulint n) /*!< in: integer in machine-dependent format */ 88{ 89 uint16 ret; 90 ut_ad(2 == sizeof ret); 91 mach_write_to_2((byte *)&ret, n); 92 return (ret); 93} 94/** The following function is used to convert a 16-bit data item 95 from the canonical format, for fast bytewise equality test 96 against memory. 97 @return integer in machine-dependent format */ 98UNIV_INLINE 99ulint mach_decode_2(uint16 n) /*!< in: 16-bit integer in canonical format */ 100{ 101 ut_ad(2 == sizeof n); 102 return (mach_read_from_2((const byte *)&n)); 103} 104 105/** The following function is used to store data in 3 consecutive 106bytes. We store the most significant byte to the lowest address. 107@param[in] b pointer to 3 bytes where to store 108@param[in] n 3 byte integer to be stored */ 109UNIV_INLINE 110void mach_write_to_3(byte *b, ulint n) { 111 ut_ad(b); 112 ut_ad((n | 0xFFFFFFUL) <= 0xFFFFFFUL); 113 114 b[0] = (byte)(n >> 16); 115 b[1] = (byte)(n >> 8); 116 b[2] = (byte)(n); 117} 118 119/** The following function is used to fetch data from 3 consecutive 120bytes. The most significant byte is at the lowest address. 121@param[in] b pointer to 3 bytes to read 122@return uint32_t integer */ 123UNIV_INLINE 124uint32_t mach_read_from_3(const byte *b) { 125 ut_ad(b); 126 return ((static_cast<uint32_t>(b[0]) << 16) | 127 (static_cast<uint32_t>(b[1]) << 8) | static_cast<uint32_t>(b[2])); 128} 129 130/** The following function is used to store data in 4 consecutive 131bytes. We store the most significant byte to the lowest address. 132@param[in] b pointer to 4 bytes where to store 133@param[in] n 4 byte integer to be stored */ 134UNIV_INLINE 135void mach_write_to_4(byte *b, ulint n) { 136 ut_ad(b); 137 138 b[0] = static_cast<byte>(n >> 24); 139 b[1] = static_cast<byte>(n >> 16); 140 b[2] = static_cast<byte>(n >> 8); 141 b[3] = static_cast<byte>(n); 142} 143 144/** The following function is used to fetch data from 4 consecutive 145bytes. The most significant byte is at the lowest address. 146@param[in] b pointer to 4 bytes to read 147@return 32 bit integer */ 148UNIV_INLINE 149uint32_t mach_read_from_4(const byte *b) { 150 ut_ad(b); 151 return ((static_cast<uint32_t>(b[0]) << 24) | 152 (static_cast<uint32_t>(b[1]) << 16) | 153 (static_cast<uint32_t>(b[2]) << 8) | static_cast<uint32_t>(b[3])); 154} 155 156/** Writes a ulint in a compressed form where the first byte codes the 157length of the stored ulint. We look at the most significant bits of 158the byte. If the most significant bit is zero, it means 1-byte storage, 159else if the 2nd bit is 0, it means 2-byte storage, else if 3rd is 0, 160it means 3-byte storage, else if 4th is 0, it means 4-byte storage, 161else the storage is 5-byte. 162@param[in] b pointer to memory where to store 163@param[in] n ulint integer (< 2^32) to be stored 164@return compressed size in bytes */ 165UNIV_INLINE 166ulint mach_write_compressed_v3(byte *b, ulint n) { 167 ut_ad(b); 168 169 if (n < 0x80) { 170 /* 0nnnnnnn (7 bits) */ 171 mach_write_to_1(b, n); 172 return (1); 173 } else if (n < 0x4000) { 174 /* 10nnnnnn nnnnnnnn (14 bits) */ 175 mach_write_to_2(b, n | 0x8000); 176 return (2); 177 } else if (n < 0x200000) { 178 /* 110nnnnn nnnnnnnn nnnnnnnn (21 bits) */ 179 mach_write_to_3(b, n | 0xC00000); 180 return (3); 181 } else if (n < 0x10000000) { 182 /* 1110nnnn nnnnnnnn nnnnnnnn nnnnnnnn (28 bits) */ 183 mach_write_to_4(b, n | 0xE0000000); 184 return (4); 185 } else { 186 /* 11110000 nnnnnnnn nnnnnnnn nnnnnnnn nnnnnnnn (32 bits) */ 187 mach_write_to_1(b, 0xF0); 188 mach_write_to_4(b + 1, n); 189 return (5); 190 } 191} 192 193/** Writes a ulint in a compressed form where the first byte codes the 194length of the stored ulint. We look at the most significant bits of 195the byte. If the most significant bit is zero, it means 1-byte storage, 196else if the 2nd bit is 0, it means 2-byte storage, else if 3rd is 0, 197it means 3-byte storage, else if 4th is 0, it means 4-byte storage, 198else the storage is 5-byte. 199@param[in] b pointer to memory where to store 200@param[in] n ulint integer (< 2^32) to be stored 201@return compressed size in bytes */ 202UNIV_INLINE 203ulint mach_write_compressed_v4(byte *b, ulint n) { 204 ut_ad(b); 205 206 if (n < 0x80) { 207 /* 0nnnnnnn (7 bits) */ 208 mach_write_to_1(b, n); 209 return (1); 210 } else if (n < 0x4000) { 211 /* 10nnnnnn nnnnnnnn (14 bits) */ 212 mach_write_to_2(b, n | 0x8000); 213 return (2); 214 } else if (n < 0x200000) { 215 /* 110nnnnn nnnnnnnn nnnnnnnn (21 bits) */ 216 mach_write_to_3(b, n | 0xC00000); 217 return (3); 218 } else if (n < 0x10000000) { 219 /* 1110nnnn nnnnnnnn nnnnnnnn nnnnnnnn (28 bits) */ 220 mach_write_to_4(b, n | 0xE0000000); 221 return (4); 222 } else if (n >= 0xFFFFFC00) { 223 /* 111110nn nnnnnnnn (10 bits) (extended) */ 224 mach_write_to_2(b, (n & 0x3FF) | 0xF800); 225 return (2); 226 } else if (n >= 0xFFFE0000) { 227 /* 1111110n nnnnnnnn nnnnnnnn (17 bits) (extended) */ 228 mach_write_to_3(b, (n & 0x1FFFF) | 0xFC0000); 229 return (3); 230 } else if (n >= 0xFF000000) { 231 /* 11111110 nnnnnnnn nnnnnnnn nnnnnnnn (24 bits) (extended) */ 232 mach_write_to_4(b, (n & 0xFFFFFF) | 0xFE000000); 233 return (4); 234 } else { 235 /* 11110000 nnnnnnnn nnnnnnnn nnnnnnnn nnnnnnnn (32 bits) */ 236 mach_write_to_1(b, 0xF0); 237 mach_write_to_4(b + 1, n); 238 return (5); 239 } 240} 241 242/** Writes a ulint in a compressed form where the first byte codes the 243length of the stored ulint. We look at the most significant bits of 244the byte. If the most significant bit is zero, it means 1-byte storage, 245else if the 2nd bit is 0, it means 2-byte storage, else if 3rd is 0, 246it means 3-byte storage, else if 4th is 0, it means 4-byte storage, 247else the storage is 5-byte. 248@param[in] b pointer to memory where to store 249@param[in] n ulint integer (< 2^32) to be stored 250@return compressed size in bytes */ 251UNIV_INLINE 252ulint mach_write_compressed(byte *b, ulint n) { 253 switch (log_detected_format) { 254 case LOG_HEADER_FORMAT_5_7_9: 255 ut_a(0); 256 return (0); 257 case LOG_HEADER_FORMAT_8_0_1: 258 case LOG_HEADER_FORMAT_8_0_3: 259 return (mach_write_compressed_v3(b, n)); 260 case LOG_HEADER_FORMAT_8_0_19: 261 return (mach_write_compressed_v4(b, n)); 262 } 263 /* make compiler happy */ 264 ut_a(0); 265 return (0); 266} 267 268/** Return the size of an ulint when written in the compressed form. 269@param[in] n ulint integer (< 2^32) to be stored 270@return compressed size in bytes */ 271UNIV_INLINE 272uint32_t mach_get_compressed_size_v3(ulint n) { 273 if (n < 0x80) { 274 /* 0nnnnnnn (7 bits) */ 275 return (1); 276 } else if (n < 0x4000) { 277 /* 10nnnnnn nnnnnnnn (14 bits) */ 278 return (2); 279 } else if (n < 0x200000) { 280 /* 110nnnnn nnnnnnnn nnnnnnnn (21 bits) */ 281 return (3); 282 } else if (n < 0x10000000) { 283 /* 1110nnnn nnnnnnnn nnnnnnnn nnnnnnnn (28 bits) */ 284 return (4); 285 } else { 286 /* 11110000 nnnnnnnn nnnnnnnn nnnnnnnn nnnnnnnn (32 bits) */ 287 return (5); 288 } 289} 290 291/** Return the size of an ulint when written in the compressed form. 292@param[in] n uint32_t integer (< 2^32) to be stored 293@return compressed size in bytes */ 294UNIV_INLINE 295uint32_t mach_get_compressed_size_v4(ulint n) { 296 if (n < 0x80) { 297 /* 0nnnnnnn (7 bits) */ 298 return (1); 299 } else if (n < 0x4000) { 300 /* 10nnnnnn nnnnnnnn (14 bits) */ 301 return (2); 302 } else if (n < 0x200000) { 303 /* 110nnnnn nnnnnnnn nnnnnnnn (21 bits) */ 304 return (3); 305 } else if (n < 0x10000000) { 306 /* 1110nnnn nnnnnnnn nnnnnnnn nnnnnnnn (28 bits) */ 307 return (4); 308 } else if (n >= 0xFFFFFC00) { 309 /* 111110nn nnnnnnnn (10 bits) (extended) */ 310 return (2); 311 } else if (n >= 0xFFFE0000) { 312 /* 1111110n nnnnnnnn nnnnnnnn (17 bits) (extended) */ 313 return (3); 314 } else if (n >= 0xFF000000) { 315 /* 11111110 nnnnnnnn nnnnnnnn nnnnnnnn (24 bits) (extended) */ 316 return (4); 317 } else { 318 /* 11110000 nnnnnnnn nnnnnnnn nnnnnnnn nnnnnnnn (32 bits) */ 319 return (5); 320 } 321} 322 323/** Return the size of an ulint when written in the compressed form. 324@param[in] n uint32_t integer (< 2^32) to be stored 325@return compressed size in bytes */ 326UNIV_INLINE 327uint32_t mach_get_compressed_size(ulint n) { 328 switch (log_detected_format) { 329 case LOG_HEADER_FORMAT_5_7_9: 330 ut_a(0); 331 return (0); 332 case LOG_HEADER_FORMAT_8_0_1: 333 case LOG_HEADER_FORMAT_8_0_3: 334 return (mach_get_compressed_size_v3(n)); 335 case LOG_HEADER_FORMAT_8_0_19: 336 return (mach_get_compressed_size_v4(n)); 337 } 338 /* make compiler happy */ 339 ut_a(0); 340 return (0); 341} 342 343/** Read a ulint in a compressed form. 344@param[in] b pointer to memory from where to read 345@return read integer (< 2^32) */ 346UNIV_INLINE 347ulint mach_read_compressed_v3(const byte *b) { 348 ulint val; 349 350 ut_ad(b); 351 352 val = mach_read_from_1(b); 353 354 if (val < 0x80) { 355 /* 0nnnnnnn (7 bits) */ 356 } else if (val < 0xC0) { 357 /* 10nnnnnn nnnnnnnn (14 bits) */ 358 val = mach_read_from_2(b) & 0x3FFF; 359 ut_ad(val > 0x7F); 360 } else if (val < 0xE0) { 361 /* 110nnnnn nnnnnnnn nnnnnnnn (21 bits) */ 362 val = mach_read_from_3(b) & 0x1FFFFF; 363 ut_ad(val > 0x3FFF); 364 } else if (val < 0xF0) { 365 /* 1110nnnn nnnnnnnn nnnnnnnn nnnnnnnn (28 bits) */ 366 val = mach_read_from_4(b) & 0xFFFFFFF; 367 ut_ad(val > 0x1FFFFF); 368 } else { 369 /* 11110000 nnnnnnnn nnnnnnnn nnnnnnnn nnnnnnnn (32 bits) */ 370 ut_ad(val == 0xF0); 371 val = mach_read_from_4(b + 1); 372 ut_ad(val > 0xFFFFFFF); 373 } 374 375 return (val); 376} 377/** Read a ulint in a compressed form. 378@param[in] b pointer to memory from where to read 379@return read integer (< 2^32) */ 380UNIV_INLINE 381ulint mach_read_compressed_v4(const byte *b) { 382 ulint val; 383 384 ut_ad(b); 385 386 val = mach_read_from_1(b); 387 388 if (val < 0x80) { 389 /* 0nnnnnnn (7 bits) */ 390 } else if (val < 0xC0) { 391 /* 10nnnnnn nnnnnnnn (14 bits) */ 392 val = mach_read_from_2(b) & 0x3FFF; 393 ut_ad(val > 0x7F); 394 } else if (val < 0xE0) { 395 /* 110nnnnn nnnnnnnn nnnnnnnn (21 bits) */ 396 val = mach_read_from_3(b) & 0x1FFFFF; 397 ut_ad(val > 0x3FFF); 398 } else if (val < 0xF0) { 399 /* 1110nnnn nnnnnnnn nnnnnnnn nnnnnnnn (28 bits) */ 400 val = mach_read_from_4(b) & 0xFFFFFFF; 401 ut_ad(val > 0x1FFFFF); 402 } else if (val < 0xF8) { 403 /* 11110000 nnnnnnnn nnnnnnnn nnnnnnnn nnnnnnnn (32 bits) */ 404 ut_ad(val == 0xF0); 405 val = mach_read_from_4(b + 1); 406 /* this can treat not-extended format also. */ 407 ut_ad(val > 0xFFFFFFF); 408 } else if (val < 0xFC) { 409 /* 111110nn nnnnnnnn (10 bits) (extended) */ 410 val = (mach_read_from_2(b) & 0x3FF) | 0xFFFFFC00; 411 } else if (val < 0xFE) { 412 /* 1111110n nnnnnnnn nnnnnnnn (17 bits) (extended) */ 413 val = (mach_read_from_3(b) & 0x1FFFF) | 0xFFFE0000; 414 ut_ad(val < 0xFFFFFC00); 415 } else { 416 /* 11111110 nnnnnnnn nnnnnnnn nnnnnnnn (24 bits) (extended) */ 417 ut_ad(val == 0xFE); 418 val = mach_read_from_3(b + 1) | 0xFF000000; 419 ut_ad(val < 0xFFFE0000); 420 } 421 422 return (val); 423} 424 425/** Read a ulint in a compressed form. 426@param[in] b pointer to memory from where to read 427@return read integer (< 2^32) */ 428UNIV_INLINE 429ulint mach_read_compressed(const byte *b) { 430 switch (log_detected_format) { 431 case LOG_HEADER_FORMAT_5_7_9: 432 ut_a(0); 433 return (0); 434 case LOG_HEADER_FORMAT_8_0_1: 435 case LOG_HEADER_FORMAT_8_0_3: 436 return (mach_read_compressed_v3(b)); 437 case LOG_HEADER_FORMAT_8_0_19: 438 return (mach_read_compressed_v4(b)); 439 } 440 /* make compiler happy */ 441 ut_a(0); 442 return (0); 443} 444 445/** Read a 32-bit integer in a compressed form. 446@param[in,out] b pointer to memory where to read; 447advanced by the number of bytes consumed 448@return unsigned value */ 449UNIV_INLINE 450ib_uint32_t mach_read_next_compressed_v3(const byte **b) { 451 ulint val = mach_read_from_1(*b); 452 453 if (val < 0x80) { 454 /* 0nnnnnnn (7 bits) */ 455 ++*b; 456 } else if (val < 0xC0) { 457 /* 10nnnnnn nnnnnnnn (14 bits) */ 458 val = mach_read_from_2(*b) & 0x3FFF; 459 ut_ad(val > 0x7F); 460 *b += 2; 461 } else if (val < 0xE0) { 462 /* 110nnnnn nnnnnnnn nnnnnnnn (21 bits) */ 463 val = mach_read_from_3(*b) & 0x1FFFFF; 464 ut_ad(val > 0x3FFF); 465 *b += 3; 466 } else if (val < 0xF0) { 467 /* 1110nnnn nnnnnnnn nnnnnnnn nnnnnnnn (28 bits) */ 468 val = mach_read_from_4(*b) & 0xFFFFFFF; 469 ut_ad(val > 0x1FFFFF); 470 *b += 4; 471 } else { 472 /* 11110000 nnnnnnnn nnnnnnnn nnnnnnnn nnnnnnnn (32 bits) */ 473 ut_ad(val == 0xF0); 474 val = mach_read_from_4(*b + 1); 475 ut_ad(val > 0xFFFFFFF); 476 *b += 5; 477 } 478 479 return (static_cast<ib_uint32_t>(val)); 480} 481 482/** Read a 32-bit integer in a compressed form. 483@param[in,out] b pointer to memory where to read; 484advanced by the number of bytes consumed 485@return unsigned value */ 486UNIV_INLINE 487ib_uint32_t mach_read_next_compressed_v4(const byte **b) { 488 ulint val = mach_read_from_1(*b); 489 490 if (val < 0x80) { 491 /* 0nnnnnnn (7 bits) */ 492 ++*b; 493 } else if (val < 0xC0) { 494 /* 10nnnnnn nnnnnnnn (14 bits) */ 495 val = mach_read_from_2(*b) & 0x3FFF; 496 ut_ad(val > 0x7F); 497 *b += 2; 498 } else if (val < 0xE0) { 499 /* 110nnnnn nnnnnnnn nnnnnnnn (21 bits) */ 500 val = mach_read_from_3(*b) & 0x1FFFFF; 501 ut_ad(val > 0x3FFF); 502 *b += 3; 503 } else if (val < 0xF0) { 504 /* 1110nnnn nnnnnnnn nnnnnnnn nnnnnnnn (28 bits) */ 505 val = mach_read_from_4(*b) & 0xFFFFFFF; 506 ut_ad(val > 0x1FFFFF); 507 *b += 4; 508 } else if (val < 0xF8) { 509 /* 11110000 nnnnnnnn nnnnnnnn nnnnnnnn nnnnnnnn (32 bits) */ 510 ut_ad(val == 0xF0); 511 val = mach_read_from_4(*b + 1); 512 /* this can treat not-extended format also. */ 513 ut_ad(val > 0xFFFFFFF); 514 *b += 5; 515 } else if (val < 0xFC) { 516 /* 111110nn nnnnnnnn (10 bits) (extended) */ 517 val = (mach_read_from_2(*b) & 0x3FF) | 0xFFFFFC00; 518 *b += 2; 519 } else if (val < 0xFE) { 520 /* 1111110n nnnnnnnn nnnnnnnn (17 bits) (extended) */ 521 val = (mach_read_from_3(*b) & 0x1FFFF) | 0xFFFE0000; 522 ut_ad(val < 0xFFFFFC00); 523 *b += 3; 524 } else { 525 /* 11111110 nnnnnnnn nnnnnnnn nnnnnnnn (24 bits) (extended) */ 526 ut_ad(val == 0xFE); 527 val = mach_read_from_3(*b + 1) | 0xFF000000; 528 ut_ad(val < 0xFFFE0000); 529 *b += 4; 530 } 531 532 return (static_cast<ib_uint32_t>(val)); 533} 534 535/** Read a 32-bit integer in a compressed form. 536@param[in,out] b pointer to memory where to read; 537advanced by the number of bytes consumed 538@return unsigned value */ 539UNIV_INLINE 540ib_uint32_t mach_read_next_compressed(const byte **b) { 541 switch (log_detected_format) { 542 case LOG_HEADER_FORMAT_5_7_9: 543 ut_a(0); 544 return (0); 545 case LOG_HEADER_FORMAT_8_0_1: 546 case LOG_HEADER_FORMAT_8_0_3: 547 return (mach_read_next_compressed_v3(b)); 548 case LOG_HEADER_FORMAT_8_0_19: 549 return (mach_read_next_compressed_v4(b)); 550 } 551 /* make compiler happy */ 552 553 ut_a(0); 554 return (0); 555} 556 557/** The following function is used to store data in 8 consecutive 558bytes. We store the most significant byte to the lowest address. 559@param[in] b pointer to 8 bytes where to store 560@param[in] n 64-bit integer (< 2^64) to be stored */ 561UNIV_INLINE 562void mach_write_to_8(void *b, ib_uint64_t n) { 563 ut_ad(b); 564 565 mach_write_to_4(static_cast<byte *>(b), (ulint)(n >> 32)); 566 mach_write_to_4(static_cast<byte *>(b) + 4, (ulint)n); 567} 568 569/** The following function is used to fetch data from 8 consecutive 570bytes. The most significant byte is at the lowest address. 571@param[in] b pointer to 8 bytes from where read 572@return 64-bit integer */ 573UNIV_INLINE 574ib_uint64_t mach_read_from_8(const byte *b) { 575 ib_uint64_t u64; 576 577 u64 = mach_read_from_4(b); 578 u64 <<= 32; 579 u64 |= mach_read_from_4(b + 4); 580 581 return (u64); 582} 583 584/** The following function is used to store data in 7 consecutive 585bytes. We store the most significant byte to the lowest address. 586@param[in] b pointer to 7 bytes where to store 587@param[in] n 56-bit integer */ 588UNIV_INLINE 589void mach_write_to_7(byte *b, ib_uint64_t n) { 590 ut_ad(b); 591 592 mach_write_to_3(b, (ulint)(n >> 32)); 593 mach_write_to_4(b + 3, (ulint)n); 594} 595 596/** The following function is used to fetch data from 7 consecutive 597bytes. The most significant byte is at the lowest address. 598@param[in] b pointer to 7 bytes to read 599@return 56-bit integer */ 600UNIV_INLINE 601ib_uint64_t mach_read_from_7(const byte *b) { 602 ut_ad(b); 603 604 return (ut_ull_create(mach_read_from_3(b), mach_read_from_4(b + 3))); 605} 606 607/** The following function is used to store data in 6 consecutive 608bytes. We store the most significant byte to the lowest address. 609@param[in] b pointer to 6 bytes where to store 610@param[in] n 48-bit integer to write */ 611UNIV_INLINE 612void mach_write_to_6(byte *b, ib_uint64_t n) { 613 ut_ad(b); 614 615 mach_write_to_2(b, (ulint)(n >> 32)); 616 mach_write_to_4(b + 2, (ulint)n); 617} 618 619/** The following function is used to fetch data from 6 consecutive 620bytes. The most significant byte is at the lowest address. 621@param[in] b pointer to 6 bytes to read 622@return 48-bit integer */ 623UNIV_INLINE 624ib_uint64_t mach_read_from_6(const byte *b) { 625 ut_ad(b); 626 627 return (ut_ull_create(mach_read_from_2(b), mach_read_from_4(b + 2))); 628} 629 630/** Writes a 64-bit integer in a compressed form (5..9 bytes). 631 @return size in bytes */ 632UNIV_INLINE 633ulint mach_u64_write_compressed( 634 byte *b, /*!< in: pointer to memory where to store */ 635 ib_uint64_t n) /*!< in: 64-bit integer to be stored */ 636{ 637 ulint size; 638 639 ut_ad(b); 640 641 size = mach_write_compressed(b, (ulint)(n >> 32)); 642 mach_write_to_4(b + size, (ulint)n); 643 644 return (size + 4); 645} 646 647/** Read a 64-bit integer in a compressed form. 648@param[in,out] b pointer to memory where to read; 649advanced by the number of bytes consumed 650@return unsigned value */ 651UNIV_INLINE 652ib_uint64_t mach_u64_read_next_compressed(const byte **b) { 653 ib_uint64_t val; 654 655 val = mach_read_next_compressed(b); 656 val <<= 32; 657 val |= mach_read_from_4(*b); 658 *b += 4; 659 return (val); 660} 661 662/** Writes a 64-bit integer in a compressed form (1..11 bytes). 663 @return size in bytes */ 664UNIV_INLINE 665ulint mach_u64_write_much_compressed( 666 byte *b, /*!< in: pointer to memory where to store */ 667 ib_uint64_t n) /*!< in: 64-bit integer to be stored */ 668{ 669 ulint size; 670 671 ut_ad(b); 672 673 if (!(n >> 32)) { 674 return (mach_write_compressed(b, (ulint)n)); 675 } 676 677 *b = (byte)0xFF; 678 size = 1 + mach_write_compressed(b + 1, (ulint)(n >> 32)); 679 680 size += mach_write_compressed(b + size, (ulint)n & 0xFFFFFFFF); 681 682 return (size); 683} 684 685/** Reads a 64-bit integer in a compressed form. 686 @return the value read 687 @see mach_parse_u64_much_compressed() */ 688UNIV_INLINE 689ib_uint64_t mach_u64_read_much_compressed( 690 const byte *b) /*!< in: pointer to memory from where to read */ 691{ 692 ib_uint64_t n; 693 694 if (*b != 0xFF) { 695 return (mach_read_compressed(b)); 696 } 697 698 b++; 699 n = mach_read_next_compressed(&b); 700 n <<= 32; 701 n |= mach_read_compressed(b); 702 703 return (n); 704} 705 706/** Read a 64-bit integer in a compressed form. 707@param[in,out] b pointer to memory where to read; 708advanced by the number of bytes consumed 709@return unsigned value */ 710UNIV_INLINE 711ib_uint64_t mach_read_next_much_compressed_v3(const byte **b) { 712 ib_uint64_t val = mach_read_from_1(*b); 713 714 if (val < 0x80) { 715 /* 0nnnnnnn (7 bits) */ 716 ++*b; 717 } else if (val < 0xC0) { 718 /* 10nnnnnn nnnnnnnn (14 bits) */ 719 val = mach_read_from_2(*b) & 0x3FFF; 720 ut_ad(val > 0x7F); 721 *b += 2; 722 } else if (val < 0xE0) { 723 /* 110nnnnn nnnnnnnn nnnnnnnn (21 bits) */ 724 val = mach_read_from_3(*b) & 0x1FFFFF; 725 ut_ad(val > 0x3FFF); 726 *b += 3; 727 } else if (val < 0xF0) { 728 /* 1110nnnn nnnnnnnn nnnnnnnn nnnnnnnn (28 bits) */ 729 val = mach_read_from_4(*b) & 0xFFFFFFF; 730 ut_ad(val > 0x1FFFFF); 731 *b += 4; 732 } else if (val == 0xF0) { 733 /* 11110000 nnnnnnnn nnnnnnnn nnnnnnnn nnnnnnnn (32 bits) */ 734 val = mach_read_from_4(*b + 1); 735 ut_ad(val > 0xFFFFFFF); 736 *b += 5; 737 } else { 738 /* 11111111 followed by up to 64 bits */ 739 ut_ad(val == 0xFF); 740 ++*b; 741 val = mach_read_next_compressed(b); 742 ut_ad(val > 0); 743 val <<= 32; 744 val |= mach_read_next_compressed(b); 745 } 746 747 return (val); 748} 749/** Read a 64-bit integer in a compressed form. 750@param[in,out] b pointer to memory where to read; 751advanced by the number of bytes consumed 752@return unsigned value */ 753UNIV_INLINE 754ib_uint64_t mach_read_next_much_compressed_v4(const byte **b) { 755 ib_uint64_t val = mach_read_from_1(*b); 756 757 if (val < 0x80) { 758 /* 0nnnnnnn (7 bits) */ 759 ++*b; 760 } else if (val < 0xC0) { 761 /* 10nnnnnn nnnnnnnn (14 bits) */ 762 val = mach_read_from_2(*b) & 0x3FFF; 763 ut_ad(val > 0x7F); 764 *b += 2; 765 } else if (val < 0xE0) { 766 /* 110nnnnn nnnnnnnn nnnnnnnn (21 bits) */ 767 val = mach_read_from_3(*b) & 0x1FFFFF; 768 ut_ad(val > 0x3FFF); 769 *b += 3; 770 } else if (val < 0xF0) { 771 /* 1110nnnn nnnnnnnn nnnnnnnn nnnnnnnn (28 bits) */ 772 val = mach_read_from_4(*b) & 0xFFFFFFF; 773 ut_ad(val > 0x1FFFFF); 774 *b += 4; 775 } else if (val < 0xF8) { 776 /* 11110000 nnnnnnnn nnnnnnnn nnnnnnnn nnnnnnnn (32 bits) */ 777 ut_ad(val == 0xF0); 778 val = mach_read_from_4(*b + 1); 779 /* this can treat not-extended format also. */ 780 ut_ad(val > 0xFFFFFFF); 781 *b += 5; 782 } else if (val < 0xFC) { 783 /* 111110nn nnnnnnnn (10 bits) (extended) */ 784 val = (mach_read_from_2(*b) & 0x3FF) | 0xFFFFFC00; 785 *b += 2; 786 } else if (val < 0xFE) { 787 /* 1111110n nnnnnnnn nnnnnnnn (17 bits) (extended) */ 788 val = (mach_read_from_3(*b) & 0x1FFFF) | 0xFFFE0000; 789 ut_ad(val < 0xFFFFFC00); 790 *b += 3; 791 } else if (val == 0xFE) { 792 /* 11111110 nnnnnnnn nnnnnnnn nnnnnnnn (24 bits) (extended) */ 793 ut_ad(val == 0xFE); 794 val = mach_read_from_3(*b + 1) | 0xFF000000; 795 ut_ad(val < 0xFFFE0000); 796 *b += 4; 797 } else { 798 /* 11111111 followed by up to 80 bits */ 799 ut_ad(val == 0xFF); 800 ++*b; 801 val = mach_read_next_compressed(b); 802 ut_ad(val > 0); 803 val <<= 32; 804 val |= mach_read_next_compressed(b); 805 } 806 807 return (val); 808} 809 810/** Read a 64-bit integer in a compressed form. 811@param[in,out] b pointer to memory where to read; 812advanced by the number of bytes consumed 813@return unsigned value */ 814UNIV_INLINE 815ib_uint64_t mach_read_next_much_compressed(const byte **b) { 816 switch (log_detected_format) { 817 case LOG_HEADER_FORMAT_5_7_9: 818 ut_a(0); 819 return (0); 820 case LOG_HEADER_FORMAT_8_0_1: 821 case LOG_HEADER_FORMAT_8_0_3: 822 return (mach_read_next_much_compressed_v3(b)); 823 case LOG_HEADER_FORMAT_8_0_19: 824 return (mach_read_next_much_compressed_v4(b)); 825 } 826 /* make compiler happy */ 827 ut_a(0); 828 return (0); 829} 830 831/** Read a 64-bit integer in a compressed form. 832@param[in,out] ptr pointer to memory where to read; 833advanced by the number of bytes consumed, or set NULL if out of space 834@param[in] end_ptr end of the buffer 835@return unsigned value */ 836UNIV_INLINE 837ib_uint64_t mach_u64_parse_compressed(const byte **ptr, const byte *end_ptr) { 838 ib_uint64_t val = 0; 839 840 if (end_ptr < *ptr + 5) { 841 *ptr = nullptr; 842 return (val); 843 } 844 845 val = mach_read_next_compressed(ptr); 846 847 if (end_ptr < *ptr + 4) { 848 *ptr = nullptr; 849 return (val); 850 } 851 852 val <<= 32; 853 val |= mach_read_from_4(*ptr); 854 *ptr += 4; 855 856 return (val); 857} 858/** Reads a double. It is stored in a little-endian format. 859 @return double read */ 860UNIV_INLINE 861double mach_double_read( 862 const byte *b) /*!< in: pointer to memory from where to read */ 863{ 864 double d; 865 ulint i; 866 byte *ptr; 867 868 ptr = (byte *)&d; 869 870 for (i = 0; i < sizeof(double); i++) { 871#ifdef WORDS_BIGENDIAN 872 ptr[sizeof(double) - i - 1] = b[i]; 873#else 874 ptr[i] = b[i]; 875#endif 876 } 877 878 return (d); 879} 880 881/** Writes a double. It is stored in a little-endian format. */ 882UNIV_INLINE 883void mach_double_write(byte *b, /*!< in: pointer to memory where to write */ 884 double d) /*!< in: double */ 885{ 886 ulint i; 887 byte *ptr; 888 889 ptr = (byte *)&d; 890 891 for (i = 0; i < sizeof(double); i++) { 892#ifdef WORDS_BIGENDIAN 893 b[i] = ptr[sizeof(double) - i - 1]; 894#else 895 b[i] = ptr[i]; 896#endif 897 } 898} 899 900/** Reads a float. It is stored in a little-endian format. 901 @return float read */ 902UNIV_INLINE 903float mach_float_read( 904 const byte *b) /*!< in: pointer to memory from where to read */ 905{ 906 float d; 907 ulint i; 908 byte *ptr; 909 910 ptr = (byte *)&d; 911 912 for (i = 0; i < sizeof(float); i++) { 913#ifdef WORDS_BIGENDIAN 914 ptr[sizeof(float) - i - 1] = b[i]; 915#else 916 ptr[i] = b[i]; 917#endif 918 } 919 920 return (d); 921} 922 923/** Writes a float. It is stored in a little-endian format. */ 924UNIV_INLINE 925void mach_float_write(byte *b, /*!< in: pointer to memory where to write */ 926 float d) /*!< in: float */ 927{ 928 ulint i; 929 byte *ptr; 930 931 ptr = (byte *)&d; 932 933 for (i = 0; i < sizeof(float); i++) { 934#ifdef WORDS_BIGENDIAN 935 b[i] = ptr[sizeof(float) - i - 1]; 936#else 937 b[i] = ptr[i]; 938#endif 939 } 940} 941 942#ifndef UNIV_HOTBACKUP 943/** Reads a ulint stored in the little-endian format. 944 @return unsigned long int */ 945UNIV_INLINE 946ulint mach_read_from_n_little_endian( 947 const byte *buf, /*!< in: from where to read */ 948 ulint buf_size) /*!< in: from how many bytes to read */ 949{ 950 ulint n = 0; 951 const byte *ptr; 952 953 ut_ad(buf_size > 0); 954 955 ptr = buf + buf_size; 956 957 for (;;) { 958 ptr--; 959 960 n = n << 8; 961 962 n += (ulint)(*ptr); 963 964 if (ptr == buf) { 965 break; 966 } 967 } 968 969 return (n); 970} 971 972/** Writes a ulint in the little-endian format. */ 973UNIV_INLINE 974void mach_write_to_n_little_endian( 975 byte *dest, /*!< in: where to write */ 976 ulint dest_size, /*!< in: into how many bytes to write */ 977 ulint n) /*!< in: unsigned long int to write */ 978{ 979 byte *end; 980 981 ut_ad(dest_size <= sizeof(ulint)); 982 ut_ad(dest_size > 0); 983 984 end = dest + dest_size; 985 986 for (;;) { 987 *dest = (byte)(n & 0xFF); 988 989 n = n >> 8; 990 991 dest++; 992 993 if (dest == end) { 994 break; 995 } 996 } 997 998 ut_ad(n == 0); 999} 1000 1001/** Reads a ulint stored in the little-endian format. 1002 @return unsigned long int */ 1003UNIV_INLINE 1004ulint mach_read_from_2_little_endian( 1005 const byte *buf) /*!< in: from where to read */ 1006{ 1007 return ((ulint)(buf[0]) | ((ulint)(buf[1]) << 8)); 1008} 1009 1010/** Writes a ulint in the little-endian format. */ 1011UNIV_INLINE 1012void mach_write_to_2_little_endian( 1013 byte *dest, /*!< in: where to write */ 1014 ulint n) /*!< in: unsigned long int to write */ 1015{ 1016 ut_ad(n < 256 * 256); 1017 1018 *dest = (byte)(n & 0xFFUL); 1019 1020 n = n >> 8; 1021 dest++; 1022 1023 *dest = (byte)(n & 0xFFUL); 1024} 1025#endif /* !UNIV_HOTBACKUP */ 1026 1027/** Convert integral type from storage byte order (big endian) to 1028 host byte order. 1029 @return integer value */ 1030UNIV_INLINE 1031ib_uint64_t mach_read_int_type( 1032 const byte *src, /*!< in: where to read from */ 1033 ulint len, /*!< in: length of src */ 1034 ibool unsigned_type) /*!< in: signed or unsigned flag */ 1035{ 1036 /* XXX this can be optimized on big-endian machines */ 1037 1038 uintmax_t ret; 1039 uint i; 1040 1041 if (unsigned_type || (src[0] & 0x80)) { 1042 ret = 0x0000000000000000ULL; 1043 } else { 1044 ret = 0xFFFFFFFFFFFFFF00ULL; 1045 } 1046 1047 if (unsigned_type) { 1048 ret |= src[0]; 1049 } else { 1050 ret |= src[0] ^ 0x80; 1051 } 1052 1053 for (i = 1; i < len; i++) { 1054 ret <<= 8; 1055 ret |= src[i]; 1056 } 1057 1058 return (ret); 1059} 1060#ifndef UNIV_HOTBACKUP 1061/** Swap byte ordering. */ 1062UNIV_INLINE 1063void mach_swap_byte_order(byte *dest, /*!< out: where to write */ 1064 const byte *from, /*!< in: where to read from */ 1065 ulint len) /*!< in: length of src */ 1066{ 1067 ut_ad(len > 0); 1068 ut_ad(len <= 8); 1069 1070 dest += len; 1071 1072 switch (len & 0x7) { 1073 case 0: 1074 *--dest = *from++; // Fall through. 1075 case 7: 1076 *--dest = *from++; // Fall through. 1077 case 6: 1078 *--dest = *from++; // Fall through. 1079 case 5: 1080 *--dest = *from++; // Fall through. 1081 case 4: 1082 *--dest = *from++; // Fall through. 1083 case 3: 1084 *--dest = *from++; // Fall through. 1085 case 2: 1086 *--dest = *from++; // Fall through. 1087 case 1: 1088 *--dest = *from; 1089 } 1090} 1091 1092/************************************************************* 1093Convert integral type from host byte order (big-endian) storage 1094byte order. */ 1095UNIV_INLINE 1096void mach_write_int_type(byte *dest, /*!< in: where to write */ 1097 const byte *src, /*!< in: where to read from */ 1098 ulint len, /*!< in: length of src */ 1099 bool usign) /*!< in: signed or unsigned flag */ 1100{ 1101 ut_ad(len >= 1 && len <= 8); 1102 1103#ifdef WORDS_BIGENDIAN 1104 memcpy(dest, src, len); 1105#else 1106 mach_swap_byte_order(dest, src, len); 1107#endif /* WORDS_BIGENDIAN */ 1108 1109 if (!usign) { 1110 *dest ^= 0x80; 1111 } 1112} 1113 1114/************************************************************* 1115Convert a ulonglong integer from host byte order to (big-endian) 1116storage byte order. */ 1117UNIV_INLINE 1118void mach_write_ulonglong(byte *dest, /*!< in: where to write */ 1119 ulonglong src, /*!< in: where to read from */ 1120 ulint len, /*!< in: length of dest */ 1121 bool usign) /*!< in: signed or unsigned flag */ 1122{ 1123 byte *ptr = reinterpret_cast<byte *>(&src); 1124 1125 ut_ad(len <= sizeof(ulonglong)); 1126 1127#ifdef WORDS_BIGENDIAN 1128 memcpy(dest, ptr + (sizeof(src) - len), len); 1129#else 1130 mach_swap_byte_order(dest, reinterpret_cast<byte *>(ptr), len); 1131#endif /* WORDS_BIGENDIAN */ 1132 1133 if (!usign) { 1134 *dest ^= 0x80; 1135 } 1136} 1137#endif /* !UNIV_HOTBACKUP */ 1138 1139/** Read 1 to 4 bytes from a file page buffered in the buffer pool. 1140@param[in] ptr pointer where to read 1141@param[in] type MLOG_1BYTE, MLOG_2BYTES, or MLOG_4BYTES 1142@return value read */ 1143UNIV_INLINE 1144uint32_t mach_read_ulint(const byte *ptr, mlog_id_t type) { 1145 switch (type) { 1146 case MLOG_1BYTE: 1147 return (mach_read_from_1(ptr)); 1148 case MLOG_2BYTES: 1149 return (mach_read_from_2(ptr)); 1150 case MLOG_4BYTES: 1151 return (mach_read_from_4(ptr)); 1152 default: 1153 break; 1154 } 1155 1156 ut_error; 1157} 1158