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