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, Suite 500, 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