1 /**********************************************************************
2 Utilities for converting data from the database file
7 Created 11/28/1995 Heikki Tuuri
8 ***********************************************************************/
12 /***********************************************************
13 The following function is used to store data in one byte. */
18 byte* b, /* in: pointer to byte where to store */
19 ulint n) /* in: ulint integer to be stored, >= 0, < 256 */
22 ut_ad((n | 0xFFUL) <= 0xFFUL);
27 /************************************************************
28 The following function is used to fetch data from one byte. */
33 /* out: ulint integer, >= 0, < 256 */
34 byte* b) /* in: pointer to byte */
37 return((ulint)(b[0]));
40 /***********************************************************
41 The following function is used to store data in two consecutive
42 bytes. We store the most significant byte to the lowest address. */
47 byte* b, /* in: pointer to two bytes where to store */
48 ulint n) /* in: ulint integer to be stored */
51 ut_ad((n | 0xFFFFUL) <= 0xFFFFUL);
53 b[0] = (byte)(n >> 8);
57 /************************************************************
58 The following function is used to fetch data from 2 consecutive
59 bytes. The most significant byte is at the lowest address. */
64 /* out: ulint integer */
65 byte* b) /* in: pointer to 2 bytes */
67 return(((ulint)(b[0]) << 8) | (ulint)(b[1]));
70 /************************************************************
71 The following function is used to convert a 16-bit data item
72 to the canonical format, for fast bytewise equality test
78 /* out: 16-bit integer in canonical format */
79 ulint n) /* in: integer in machine-dependent format */
82 ut_ad(2 == sizeof ret);
83 mach_write_to_2((byte*) &ret, n);
86 /************************************************************
87 The following function is used to convert a 16-bit data item
88 from the canonical format, for fast bytewise equality test
94 /* out: integer in machine-dependent format */
95 uint16 n) /* in: 16-bit integer in canonical format */
98 return(mach_read_from_2((byte*) &n));
101 /***********************************************************
102 The following function is used to store data in 3 consecutive
103 bytes. We store the most significant byte to the lowest address. */
108 byte* b, /* in: pointer to 3 bytes where to store */
109 ulint n) /* in: ulint integer to be stored */
112 ut_ad((n | 0xFFFFFFUL) <= 0xFFFFFFUL);
114 b[0] = (byte)(n >> 16);
115 b[1] = (byte)(n >> 8);
119 /************************************************************
120 The following function is used to fetch data from 3 consecutive
121 bytes. The most significant byte is at the lowest address. */
126 /* out: ulint integer */
127 byte* b) /* in: pointer to 3 bytes */
130 return( ((ulint)(b[0]) << 16)
131 | ((ulint)(b[1]) << 8)
136 /***********************************************************
137 The following function is used to store data in four consecutive
138 bytes. We store the most significant byte to the lowest address. */
143 byte* b, /* in: pointer to four bytes where to store */
144 ulint n) /* in: ulint integer to be stored */
148 b[0] = (byte)(n >> 24);
149 b[1] = (byte)(n >> 16);
150 b[2] = (byte)(n >> 8);
154 /************************************************************
155 The following function is used to fetch data from 4 consecutive
156 bytes. The most significant byte is at the lowest address. */
161 /* out: ulint integer */
162 byte* b) /* in: pointer to four bytes */
165 return( ((ulint)(b[0]) << 24)
166 | ((ulint)(b[1]) << 16)
167 | ((ulint)(b[2]) << 8)
172 /*************************************************************
173 Writes a ulint in a compressed form where the first byte codes the
174 length of the stored ulint. We look at the most significant bits of
175 the byte. If the most significant bit is zero, it means 1-byte storage,
176 else if the 2nd bit is 0, it means 2-byte storage, else if 3rd is 0,
177 it means 3-byte storage, else if 4th is 0, it means 4-byte storage,
178 else the storage is 5-byte. */
181 mach_write_compressed(
182 /*==================*/
183 /* out: compressed size in bytes */
184 byte* b, /* in: pointer to memory where to store */
185 ulint n) /* in: ulint integer (< 2^32) to be stored */
190 mach_write_to_1(b, n);
192 } else if (n < 0x4000UL) {
193 mach_write_to_2(b, n | 0x8000UL);
195 } else if (n < 0x200000UL) {
196 mach_write_to_3(b, n | 0xC00000UL);
198 } else if (n < 0x10000000UL) {
199 mach_write_to_4(b, n | 0xE0000000UL);
202 mach_write_to_1(b, 0xF0UL);
203 mach_write_to_4(b + 1, n);
208 /*************************************************************
209 Returns the size of a ulint when written in the compressed form. */
212 mach_get_compressed_size(
213 /*=====================*/
214 /* out: compressed size in bytes */
215 ulint n) /* in: ulint integer (< 2^32) to be stored */
219 } else if (n < 0x4000UL) {
221 } else if (n < 0x200000UL) {
223 } else if (n < 0x10000000UL) {
230 /*************************************************************
231 Reads a ulint in a compressed form. */
234 mach_read_compressed(
235 /*=================*/
236 /* out: read integer (< 2^32) */
237 byte* b) /* in: pointer to memory from where to read */
243 flag = mach_read_from_1(b);
247 } else if (flag < 0xC0UL) {
248 return(mach_read_from_2(b) & 0x7FFFUL);
249 } else if (flag < 0xE0UL) {
250 return(mach_read_from_3(b) & 0x3FFFFFUL);
251 } else if (flag < 0xF0UL) {
252 return(mach_read_from_4(b) & 0x1FFFFFFFUL);
254 ut_ad(flag == 0xF0UL);
255 return(mach_read_from_4(b + 1));
259 /***********************************************************
260 The following function is used to store data in 8 consecutive
261 bytes. We store the most significant byte to the lowest address. */
266 byte* b, /* in: pointer to 8 bytes where to store */
267 dulint n) /* in: dulint integer to be stored */
271 mach_write_to_4(b, ut_dulint_get_high(n));
272 mach_write_to_4(b + 4, ut_dulint_get_low(n));
275 /************************************************************
276 The following function is used to fetch data from 8 consecutive
277 bytes. The most significant byte is at the lowest address. */
282 /* out: dulint integer */
283 byte* b) /* in: pointer to 8 bytes */
290 high = mach_read_from_4(b);
291 low = mach_read_from_4(b + 4);
293 return(ut_dulint_create(high, low));
296 /***********************************************************
297 The following function is used to store data in 7 consecutive
298 bytes. We store the most significant byte to the lowest address. */
303 byte* b, /* in: pointer to 7 bytes where to store */
304 dulint n) /* in: dulint integer to be stored */
308 mach_write_to_3(b, ut_dulint_get_high(n));
309 mach_write_to_4(b + 3, ut_dulint_get_low(n));
312 /************************************************************
313 The following function is used to fetch data from 7 consecutive
314 bytes. The most significant byte is at the lowest address. */
319 /* out: dulint integer */
320 byte* b) /* in: pointer to 7 bytes */
327 high = mach_read_from_3(b);
328 low = mach_read_from_4(b + 3);
330 return(ut_dulint_create(high, low));
333 /***********************************************************
334 The following function is used to store data in 6 consecutive
335 bytes. We store the most significant byte to the lowest address. */
340 byte* b, /* in: pointer to 6 bytes where to store */
341 dulint n) /* in: dulint integer to be stored */
345 mach_write_to_2(b, ut_dulint_get_high(n));
346 mach_write_to_4(b + 2, ut_dulint_get_low(n));
349 /************************************************************
350 The following function is used to fetch data from 6 consecutive
351 bytes. The most significant byte is at the lowest address. */
356 /* out: dulint integer */
357 byte* b) /* in: pointer to 7 bytes */
364 high = mach_read_from_2(b);
365 low = mach_read_from_4(b + 2);
367 return(ut_dulint_create(high, low));
370 /*************************************************************
371 Writes a dulint in a compressed form (5..9 bytes). */
374 mach_dulint_write_compressed(
375 /*=========================*/
376 /* out: size in bytes */
377 byte* b, /* in: pointer to memory where to store */
378 dulint n) /* in: dulint integer to be stored */
384 size = mach_write_compressed(b, ut_dulint_get_high(n));
385 mach_write_to_4(b + size, ut_dulint_get_low(n));
390 /*************************************************************
391 Returns the size of a dulint when written in the compressed form. */
394 mach_dulint_get_compressed_size(
395 /*============================*/
396 /* out: compressed size in bytes */
397 dulint n) /* in: dulint integer to be stored */
399 return(4 + mach_get_compressed_size(ut_dulint_get_high(n)));
402 /*************************************************************
403 Reads a dulint in a compressed form. */
406 mach_dulint_read_compressed(
407 /*========================*/
408 /* out: read dulint */
409 byte* b) /* in: pointer to memory from where to read */
417 high = mach_read_compressed(b);
419 size = mach_get_compressed_size(high);
421 low = mach_read_from_4(b + size);
423 return(ut_dulint_create(high, low));
426 /*************************************************************
427 Writes a dulint in a compressed form (1..11 bytes). */
430 mach_dulint_write_much_compressed(
431 /*==============================*/
432 /* out: size in bytes */
433 byte* b, /* in: pointer to memory where to store */
434 dulint n) /* in: dulint integer to be stored */
440 if (ut_dulint_get_high(n) == 0) {
441 return(mach_write_compressed(b, ut_dulint_get_low(n)));
445 size = 1 + mach_write_compressed(b + 1, ut_dulint_get_high(n));
447 size += mach_write_compressed(b + size, ut_dulint_get_low(n));
452 /*************************************************************
453 Returns the size of a dulint when written in the compressed form. */
456 mach_dulint_get_much_compressed_size(
457 /*=================================*/
458 /* out: compressed size in bytes */
459 dulint n) /* in: dulint integer to be stored */
461 if (0 == ut_dulint_get_high(n)) {
462 return(mach_get_compressed_size(ut_dulint_get_low(n)));
465 return(1 + mach_get_compressed_size(ut_dulint_get_high(n))
466 + mach_get_compressed_size(ut_dulint_get_low(n)));
469 /*************************************************************
470 Reads a dulint in a compressed form. */
473 mach_dulint_read_much_compressed(
474 /*=============================*/
475 /* out: read dulint */
476 byte* b) /* in: pointer to memory from where to read */
484 if (*b != (byte)0xFF) {
488 high = mach_read_compressed(b + 1);
490 size = 1 + mach_get_compressed_size(high);
493 low = mach_read_compressed(b + size);
495 return(ut_dulint_create(high, low));
498 /*************************************************************
499 Reads a double. It is stored in a little-endian format. */
504 /* out: double read */
505 const byte* b) /* in: pointer to memory from where to read */
513 for (i = 0; i < sizeof(double); i++) {
514 #ifdef WORDS_BIGENDIAN
515 ptr[sizeof(double) - i - 1] = b[i];
524 /*************************************************************
525 Writes a double. It is stored in a little-endian format. */
530 byte* b, /* in: pointer to memory where to write */
531 double d) /* in: double */
538 for (i = 0; i < sizeof(double); i++) {
539 #ifdef WORDS_BIGENDIAN
540 b[i] = ptr[sizeof(double) - i - 1];
547 /*************************************************************
548 Reads a float. It is stored in a little-endian format. */
553 /* out: float read */
554 const byte* b) /* in: pointer to memory from where to read */
562 for (i = 0; i < sizeof(float); i++) {
563 #ifdef WORDS_BIGENDIAN
564 ptr[sizeof(float) - i - 1] = b[i];
573 /*************************************************************
574 Writes a float. It is stored in a little-endian format. */
579 byte* b, /* in: pointer to memory where to write */
580 float d) /* in: float */
587 for (i = 0; i < sizeof(float); i++) {
588 #ifdef WORDS_BIGENDIAN
589 b[i] = ptr[sizeof(float) - i - 1];
596 /*************************************************************
597 Reads a ulint stored in the little-endian format. */
600 mach_read_from_n_little_endian(
601 /*===========================*/
602 /* out: unsigned long int */
603 byte* buf, /* in: from where to read */
604 ulint buf_size) /* in: from how many bytes to read */
609 ut_ad(buf_size <= sizeof(ulint));
612 ptr = buf + buf_size;
629 /*************************************************************
630 Writes a ulint in the little-endian format. */
633 mach_write_to_n_little_endian(
634 /*==========================*/
635 byte* dest, /* in: where to write */
636 ulint dest_size, /* in: into how many bytes to write */
637 ulint n) /* in: unsigned long int to write */
641 ut_ad(dest_size <= sizeof(ulint));
642 ut_ad(dest_size > 0);
644 end = dest + dest_size;
647 *dest = (byte)(n & 0xFF);
661 /*************************************************************
662 Reads a ulint stored in the little-endian format. */
665 mach_read_from_2_little_endian(
666 /*===========================*/
667 /* out: unsigned long int */
668 byte* buf) /* in: from where to read */
670 return((ulint)(buf[0]) | ((ulint)(buf[1]) << 8));
673 /*************************************************************
674 Writes a ulint in the little-endian format. */
677 mach_write_to_2_little_endian(
678 /*==========================*/
679 byte* dest, /* in: where to write */
680 ulint n) /* in: unsigned long int to write */
682 ut_ad(n < 256 * 256);
684 *dest = (byte)(n & 0xFFUL);
689 *dest = (byte)(n & 0xFFUL);
692 /*************************************************************
693 Convert integral type from storage byte order (big endian) to
699 /* out: integer value */
700 const byte* src, /* in: where to read from */
701 ulint len, /* in: length of src */
702 ibool unsigned_type) /* in: signed or unsigned flag */
704 /* XXX this can be optimized on big-endian machines */
709 if (unsigned_type || (src[0] & 0x80)) {
711 ret = 0x0000000000000000ULL;
714 ret = 0xFFFFFFFFFFFFFF00ULL;
722 ret |= src[0] ^ 0x80;
725 for (i = 1; i < len; i++) {