mySQL 5.0.11 sources for tomato
[tomato.git] / release / src / router / mysql / storage / innobase / include / mach0data.ic
blobfceb8017121505b3038b90a81c2c5245e5884cb2
1 /**********************************************************************
2 Utilities for converting data from the database file
3 to the machine format.
5 (c) 1995 Innobase Oy
7 Created 11/28/1995 Heikki Tuuri
8 ***********************************************************************/
10 #include "ut0mem.h"
12 /***********************************************************
13 The following function is used to store data in one byte. */
14 UNIV_INLINE
15 void
16 mach_write_to_1(
17 /*============*/
18         byte*   b,      /* in: pointer to byte where to store */
19         ulint   n)      /* in: ulint integer to be stored, >= 0, < 256 */
21         ut_ad(b);
22         ut_ad((n | 0xFFUL) <= 0xFFUL);
24         b[0] = (byte)n;
27 /************************************************************
28 The following function is used to fetch data from one byte. */
29 UNIV_INLINE
30 ulint
31 mach_read_from_1(
32 /*=============*/
33                         /* out: ulint integer, >= 0, < 256 */
34         byte*   b)      /* in: pointer to byte */
36         ut_ad(b);
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. */
43 UNIV_INLINE
44 void
45 mach_write_to_2(
46 /*============*/
47         byte*   b,      /* in: pointer to two bytes where to store */
48         ulint   n)      /* in: ulint integer to be stored */
50         ut_ad(b);
51         ut_ad((n | 0xFFFFUL) <= 0xFFFFUL);
53         b[0] = (byte)(n >> 8);
54         b[1] = (byte)(n);
57 /************************************************************
58 The following function is used to fetch data from 2 consecutive
59 bytes. The most significant byte is at the lowest address. */
60 UNIV_INLINE
61 ulint
62 mach_read_from_2(
63 /*=============*/
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
73 against memory. */
74 UNIV_INLINE
75 uint16
76 mach_encode_2(
77 /*==========*/
78                         /* out: 16-bit integer in canonical format */
79         ulint   n)      /* in: integer in machine-dependent format */
81         uint16  ret;
82         ut_ad(2 == sizeof ret);
83         mach_write_to_2((byte*) &ret, n);
84         return(ret);
86 /************************************************************
87 The following function is used to convert a 16-bit data item
88 from the canonical format, for fast bytewise equality test
89 against memory. */
90 UNIV_INLINE
91 ulint
92 mach_decode_2(
93 /*==========*/
94                         /* out: integer in machine-dependent format */
95         uint16  n)      /* in: 16-bit integer in canonical format */
97         ut_ad(2 == sizeof n);
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. */
104 UNIV_INLINE
105 void
106 mach_write_to_3(
107 /*============*/
108         byte*   b,      /* in: pointer to 3 bytes where to store */
109         ulint   n)      /* in: ulint integer to be stored */
111         ut_ad(b);
112         ut_ad((n | 0xFFFFFFUL) <= 0xFFFFFFUL);
114         b[0] = (byte)(n >> 16);
115         b[1] = (byte)(n >> 8);
116         b[2] = (byte)(n);
119 /************************************************************
120 The following function is used to fetch data from 3 consecutive
121 bytes. The most significant byte is at the lowest address. */
122 UNIV_INLINE
123 ulint
124 mach_read_from_3(
125 /*=============*/
126                         /* out: ulint integer */
127         byte*   b)      /* in: pointer to 3 bytes */
129         ut_ad(b);
130         return( ((ulint)(b[0]) << 16)
131                 | ((ulint)(b[1]) << 8)
132                 | (ulint)(b[2])
133                 );
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. */
139 UNIV_INLINE
140 void
141 mach_write_to_4(
142 /*============*/
143         byte*   b,      /* in: pointer to four bytes where to store */
144         ulint   n)      /* in: ulint integer to be stored */
146         ut_ad(b);
148         b[0] = (byte)(n >> 24);
149         b[1] = (byte)(n >> 16);
150         b[2] = (byte)(n >> 8);
151         b[3] = (byte)n;
154 /************************************************************
155 The following function is used to fetch data from 4 consecutive
156 bytes. The most significant byte is at the lowest address. */
157 UNIV_INLINE
158 ulint
159 mach_read_from_4(
160 /*=============*/
161                         /* out: ulint integer */
162         byte*   b)      /* in: pointer to four bytes */
164         ut_ad(b);
165         return( ((ulint)(b[0]) << 24)
166                 | ((ulint)(b[1]) << 16)
167                 | ((ulint)(b[2]) << 8)
168                 | (ulint)(b[3])
169                 );
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. */
179 UNIV_INLINE
180 ulint
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 */
187         ut_ad(b);
189         if (n < 0x80UL) {
190                 mach_write_to_1(b, n);
191                 return(1);
192         } else if (n < 0x4000UL) {
193                 mach_write_to_2(b, n | 0x8000UL);
194                 return(2);
195         } else if (n < 0x200000UL) {
196                 mach_write_to_3(b, n | 0xC00000UL);
197                 return(3);
198         } else if (n < 0x10000000UL) {
199                 mach_write_to_4(b, n | 0xE0000000UL);
200                 return(4);
201         } else {
202                 mach_write_to_1(b, 0xF0UL);
203                 mach_write_to_4(b + 1, n);
204                 return(5);
205         }
208 /*************************************************************
209 Returns the size of a ulint when written in the compressed form. */
210 UNIV_INLINE
211 ulint
212 mach_get_compressed_size(
213 /*=====================*/
214                         /* out: compressed size in bytes */
215         ulint   n)      /* in: ulint integer (< 2^32) to be stored */
217         if (n < 0x80UL) {
218                 return(1);
219         } else if (n < 0x4000UL) {
220                 return(2);
221         } else if (n < 0x200000UL) {
222                 return(3);
223         } else if (n < 0x10000000UL) {
224                 return(4);
225         } else {
226                 return(5);
227         }
230 /*************************************************************
231 Reads a ulint in a compressed form. */
232 UNIV_INLINE
233 ulint
234 mach_read_compressed(
235 /*=================*/
236                         /* out: read integer (< 2^32) */
237         byte*   b)      /* in: pointer to memory from where to read */
239         ulint   flag;
241         ut_ad(b);
243         flag = mach_read_from_1(b);
245         if (flag < 0x80UL) {
246                 return(flag);
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);
253         } else {
254                 ut_ad(flag == 0xF0UL);
255                 return(mach_read_from_4(b + 1));
256         }
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. */
262 UNIV_INLINE
263 void
264 mach_write_to_8(
265 /*============*/
266         byte*   b,      /* in: pointer to 8 bytes where to store */
267         dulint  n)      /* in: dulint integer to be stored */
269         ut_ad(b);
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. */
278 UNIV_INLINE
279 dulint
280 mach_read_from_8(
281 /*=============*/
282                         /* out: dulint integer */
283         byte*   b)      /* in: pointer to 8 bytes */
285         ulint   high;
286         ulint   low;
288         ut_ad(b);
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. */
299 UNIV_INLINE
300 void
301 mach_write_to_7(
302 /*============*/
303         byte*   b,      /* in: pointer to 7 bytes where to store */
304         dulint  n)      /* in: dulint integer to be stored */
306         ut_ad(b);
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. */
315 UNIV_INLINE
316 dulint
317 mach_read_from_7(
318 /*=============*/
319                         /* out: dulint integer */
320         byte*   b)      /* in: pointer to 7 bytes */
322         ulint   high;
323         ulint   low;
325         ut_ad(b);
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. */
336 UNIV_INLINE
337 void
338 mach_write_to_6(
339 /*============*/
340         byte*   b,      /* in: pointer to 6 bytes where to store */
341         dulint  n)      /* in: dulint integer to be stored */
343         ut_ad(b);
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. */
352 UNIV_INLINE
353 dulint
354 mach_read_from_6(
355 /*=============*/
356                         /* out: dulint integer */
357         byte*   b)      /* in: pointer to 7 bytes */
359         ulint   high;
360         ulint   low;
362         ut_ad(b);
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). */
372 UNIV_INLINE
373 ulint
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 */
380         ulint   size;
382         ut_ad(b);
384         size = mach_write_compressed(b, ut_dulint_get_high(n));
385         mach_write_to_4(b + size, ut_dulint_get_low(n));
387         return(size + 4);
390 /*************************************************************
391 Returns the size of a dulint when written in the compressed form. */
392 UNIV_INLINE
393 ulint
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. */
404 UNIV_INLINE
405 dulint
406 mach_dulint_read_compressed(
407 /*========================*/
408                         /* out: read dulint */
409         byte*   b)      /* in: pointer to memory from where to read */
411         ulint   high;
412         ulint   low;
413         ulint   size;
415         ut_ad(b);
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). */
428 UNIV_INLINE
429 ulint
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 */
436         ulint   size;
438         ut_ad(b);
440         if (ut_dulint_get_high(n) == 0) {
441                 return(mach_write_compressed(b, ut_dulint_get_low(n)));
442         }
444         *b = (byte)0xFF;
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));
449         return(size);
452 /*************************************************************
453 Returns the size of a dulint when written in the compressed form. */
454 UNIV_INLINE
455 ulint
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)));
463         }
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. */
471 UNIV_INLINE
472 dulint
473 mach_dulint_read_much_compressed(
474 /*=============================*/
475                         /* out: read dulint */
476         byte*   b)      /* in: pointer to memory from where to read */
478         ulint   high;
479         ulint   low;
480         ulint   size;
482         ut_ad(b);
484         if (*b != (byte)0xFF) {
485                 high = 0;
486                 size = 0;
487         } else {
488                 high = mach_read_compressed(b + 1);
490                 size = 1 + mach_get_compressed_size(high);
491         }
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. */
500 UNIV_INLINE
501 double
502 mach_double_read(
503 /*=============*/
504                                 /* out: double read */
505         const byte*     b)      /* in: pointer to memory from where to read */
507         double  d;
508         ulint   i;
509         byte*   ptr;
511         ptr = (byte*)&d;
513         for (i = 0; i < sizeof(double); i++) {
514 #ifdef WORDS_BIGENDIAN
515                 ptr[sizeof(double) - i - 1] = b[i];
516 #else
517                 ptr[i] = b[i];
518 #endif
519         }
521         return(d);
524 /*************************************************************
525 Writes a double. It is stored in a little-endian format. */
526 UNIV_INLINE
527 void
528 mach_double_write(
529 /*==============*/
530         byte*   b,      /* in: pointer to memory where to write */
531         double  d)      /* in: double */
533         ulint   i;
534         byte*   ptr;
536         ptr = (byte*)&d;
538         for (i = 0; i < sizeof(double); i++) {
539 #ifdef WORDS_BIGENDIAN
540                 b[i] = ptr[sizeof(double) - i - 1];
541 #else
542                 b[i] = ptr[i];
543 #endif
544         }
547 /*************************************************************
548 Reads a float. It is stored in a little-endian format. */
549 UNIV_INLINE
550 float
551 mach_float_read(
552 /*============*/
553                                 /* out: float read */
554         const byte*     b)      /* in: pointer to memory from where to read */
556         float   d;
557         ulint   i;
558         byte*   ptr;
560         ptr = (byte*)&d;
562         for (i = 0; i < sizeof(float); i++) {
563 #ifdef WORDS_BIGENDIAN
564                 ptr[sizeof(float) - i - 1] = b[i];
565 #else
566                 ptr[i] = b[i];
567 #endif
568         }
570         return(d);
573 /*************************************************************
574 Writes a float. It is stored in a little-endian format. */
575 UNIV_INLINE
576 void
577 mach_float_write(
578 /*=============*/
579         byte*   b,      /* in: pointer to memory where to write */
580         float   d)      /* in: float */
582         ulint   i;
583         byte*   ptr;
585         ptr = (byte*)&d;
587         for (i = 0; i < sizeof(float); i++) {
588 #ifdef WORDS_BIGENDIAN
589                 b[i] = ptr[sizeof(float) - i - 1];
590 #else
591                 b[i] = ptr[i];
592 #endif
593         }
596 /*************************************************************
597 Reads a ulint stored in the little-endian format. */
598 UNIV_INLINE
599 ulint
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 */
606         ulint   n       = 0;
607         byte*   ptr;
609         ut_ad(buf_size <= sizeof(ulint));
610         ut_ad(buf_size > 0);
612         ptr = buf + buf_size;
614         for (;;) {
615                 ptr--;
617                 n = n << 8;
619                 n += (ulint)(*ptr);
621                 if (ptr == buf) {
622                         break;
623                 }
624         }
626         return(n);
629 /*************************************************************
630 Writes a ulint in the little-endian format. */
631 UNIV_INLINE
632 void
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 */
639         byte*   end;
641         ut_ad(dest_size <= sizeof(ulint));
642         ut_ad(dest_size > 0);
644         end = dest + dest_size;
646         for (;;) {
647                 *dest = (byte)(n & 0xFF);
649                 n = n >> 8;
651                 dest++;
653                 if (dest == end) {
654                         break;
655                 }
656         }
658         ut_ad(n == 0);
661 /*************************************************************
662 Reads a ulint stored in the little-endian format. */
663 UNIV_INLINE
664 ulint
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. */
675 UNIV_INLINE
676 void
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);
686         n = n >> 8;
687         dest++;
689         *dest = (byte)(n & 0xFFUL);
692 /*************************************************************
693 Convert integral type from storage byte order (big endian) to
694 host byte order. */
695 UNIV_INLINE
696 ullint
697 mach_read_int_type(
698 /*===============*/
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 */
706         ullint  ret;
707         uint    i;
709         if (unsigned_type || (src[0] & 0x80)) {
711                 ret = 0x0000000000000000ULL;
712         } else {
714                 ret = 0xFFFFFFFFFFFFFF00ULL;
715         }
717         if (unsigned_type) {
719                 ret |= src[0];
720         } else {
722                 ret |= src[0] ^ 0x80;
723         }
725         for (i = 1; i < len; i++) {
726                 ret <<= 8;
727                 ret |= src[i];
728         }
730         return(ret);