Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 0dd1d444 in mainline


Ignore:
Timestamp:
2009-03-30T22:22:05Z (12 years ago)
Author:
Jiri Svoboda <jirik.svoboda@…>
Branches:
lfn, master
Children:
32704cb
Parents:
c18e666
Message:

Slightly 'decompile' character decoder.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/lib/string.c

    rc18e666 r0dd1d444  
    4545char invalch = '?';
    4646
     47/** Byte mask consisting of bits 0 - (@n - 1) */
     48#define LO_MASK_8(n) ((uint8_t)((1 << (n)) - 1))
     49
     50/** Number of data bits in a UTF-8 continuation byte. */
     51#define CONT_BITS 6
     52
    4753/** Decode a single UTF-8 character from a NULL-terminated string.
    4854 *
     
    6167wchar_t utf8_decode(const char *str, index_t *index, index_t limit)
    6268{
    63         uint8_t c1;           /* First plain character from str */
    64         uint8_t c2;           /* Second plain character from str */
    65         uint8_t c3;           /* Third plain character from str */
    66         uint8_t c4;           /* Fourth plain character from str */
    67        
     69        uint8_t b0, b;          /* Bytes read from str. */
     70        wchar_t ch;
     71
     72        int b0_bits;            /* Data bits in first byte. */
     73        int cbytes;             /* Number of continuation bytes. */
     74
    6875        if (*index > limit)
    6976                return invalch;
    70        
    71         c1 = (uint8_t) str[*index];
    72        
    73         if ((c1 & 0x80) == 0) {
    74                 /* Plain ASCII (code points 0 .. 127) */
    75                 return (wchar_t) c1;
    76         }
    77        
    78         if ((c1 & 0xe0) == 0xc0) {
    79                 /* Code points 128 .. 2047 */
    80                 if (*index + 1 > limit)
     77
     78        b0 = (uint8_t) str[*index];
     79
     80        /* Determine code length. */
     81
     82        if ((b0 & 0x80) == 0) {
     83                /* 0xxxxxxx (Plain ASCII) */
     84                b0_bits = 7;
     85                cbytes = 0;
     86        } else if ((b0 & 0xe0) == 0xc0) {
     87                /* 110xxxxx 10xxxxxx */
     88                b0_bits = 5;
     89                cbytes = 1;
     90        } else if ((b0 & 0xf0) == 0xe0) {
     91                /* 1110xxxx 10xxxxxx 10xxxxxx */
     92                b0_bits = 4;
     93                cbytes = 2;
     94        } else if ((b0 & 0xf8) == 0xf0) {
     95                /* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
     96                b0_bits = 3;
     97                cbytes = 3;
     98        } else {
     99                /* 10xxxxxx -- unexpected continuation byte. */
     100                return invalch;
     101        }
     102
     103        if (*index + cbytes > limit) {
     104                return invalch;
     105        }
     106
     107        ch = b0 & LO_MASK_8(b0_bits);
     108
     109        /* Decode continuation bytes. */
     110        while (cbytes > 0) {
     111                b = (uint8_t) str[*index + 1];
     112                ++(*index);
     113
     114                /* Must be 10xxxxxx. */
     115                if ((b & 0xc0) != 0x80) {
    81116                        return invalch;
    82                
    83                 c2 = (uint8_t) str[*index + 1];
    84                 if ((c2 & 0xc0) == 0x80) {
    85                         (*index)++;
    86                         return ((wchar_t) ((c1 & 0x1f) << 6) | (c2 & 0x3f));
    87                 } else
    88                         return invalch;
    89         }
    90        
    91         if ((c1 & 0xf0) == 0xe0) {
    92                 /* Code points 2048 .. 65535 */
    93                 if (*index + 2 > limit)
    94                         return invalch;
    95                
    96                 c2 = (uint8_t) str[*index + 1];
    97                 if ((c2 & 0xc0) == 0x80) {
    98                         (*index)++;
    99                         c3 = (uint8_t) str[*index + 1];
    100                         if ((c3 & 0xc0) == 0x80) {
    101                                 (*index)++;
    102                                 return ((wchar_t) ((c1 & 0x0f) << 12) | ((c2 & 0x3f) << 6) | (c3 & 0x3f));
    103                         } else
    104                                 return invalch;
    105                 } else
    106                         return invalch;
    107         }
    108        
    109         if ((c1 & 0xf8) == 0xf0) {
    110                 /* Code points 65536 .. 1114111 */
    111                 if (*index + 3 > limit)
    112                         return invalch;
    113                
    114                 c2 = (uint8_t) str[*index + 1];
    115                 if ((c2 & 0xc0) == 0x80) {
    116                         (*index)++;
    117                         c3 = (uint8_t) str[*index + 1];
    118                         if ((c3 & 0xc0) == 0x80) {
    119                                 (*index)++;
    120                                 c4 = (uint8_t) str[*index + 1];
    121                                 if ((c4 & 0xc0) == 0x80) {
    122                                         (*index)++;
    123                                         return ((wchar_t) ((c1 & 0x07) << 18) | ((c2 & 0x3f) << 12) | ((c3 & 0x3f) << 6) | (c4 & 0x3f));
    124                                 } else
    125                                         return invalch;
    126                         } else
    127                                 return invalch;
    128                 } else
    129                         return invalch;
    130         }
    131        
    132         return invalch;
     117                }
     118
     119                /* Shift data bits to ch. */
     120                ch = (ch << CONT_BITS) | (wchar_t) (b & LO_MASK_8(CONT_BITS));
     121                --cbytes;
     122        }
     123
     124        return ch;
    133125}
    134126
Note: See TracChangeset for help on using the changeset viewer.