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