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