Changeset 32704cb in mainline for kernel/generic/src/lib/string.c


Ignore:
Timestamp:
2009-03-31T18:50:09Z (15 years ago)
Author:
Jiri Svoboda <jirik.svoboda@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
b54d2f1
Parents:
0dd1d444
Message:

Slightly decompile character encoder.

File:
1 edited

Legend:

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

    r0dd1d444 r32704cb  
    4545char invalch = '?';
    4646
    47 /** Byte mask consisting of bits 0 - (@n - 1) */
     47/** Byte mask consisting of lowest @n bits (out of eight). */
    4848#define LO_MASK_8(n) ((uint8_t)((1 << (n)) - 1))
     49
     50/** Byte mask consisting of lowest @n bits (out of 32). */
     51#define LO_MASK_32(n) ((uint32_t)((1 << (n)) - 1))
     52
     53/** Byte mask consisting of highest @n bits (out of eight). */
     54#define HI_MASK_8(n) (~LO_MASK_8(8 - (n)))
    4955
    5056/** Number of data bits in a UTF-8 continuation byte. */
     
    145151bool utf8_encode(const wchar_t ch, char *str, index_t *index, index_t limit)
    146152{
     153        uint32_t cc;            /* Unsigned version of ch. */
     154
     155        int cbytes;             /* Number of continuation bytes. */
     156        int b0_bits;            /* Number of data bits in first byte. */
     157        int i;
     158
    147159        if (*index > limit)
    148160                return false;
    149        
    150         if ((ch >= 0) && (ch <= 127)) {
    151                 /* Plain ASCII (code points 0 .. 127) */
    152                 str[*index] = ch & 0x7f;
    153                 return true;
    154         }
    155        
    156         if ((ch >= 128) && (ch <= 2047)) {
    157                 /* Code points 128 .. 2047 */
    158                 if (*index + 1 > limit)
    159                         return false;
    160                
    161                 str[*index] = 0xc0 | ((ch >> 6) & 0x1f);
    162                 (*index)++;
    163                 str[*index] = 0x80 | (ch & 0x3f);
    164                 return true;
    165         }
    166        
    167         if ((ch >= 2048) && (ch <= 65535)) {
    168                 /* Code points 2048 .. 65535 */
    169                 if (*index + 2 > limit)
    170                         return false;
    171                
    172                 str[*index] = 0xe0 | ((ch >> 12) & 0x0f);
    173                 (*index)++;
    174                 str[*index] = 0x80 | ((ch >> 6) & 0x3f);
    175                 (*index)++;
    176                 str[*index] = 0x80 | (ch & 0x3f);
    177                 return true;
    178         }
    179        
    180         if ((ch >= 65536) && (ch <= 1114111)) {
    181                 /* Code points 65536 .. 1114111 */
    182                 if (*index + 3 > limit)
    183                         return false;
    184                
    185                 str[*index] = 0xf0 | ((ch >> 18) & 0x07);
    186                 (*index)++;
    187                 str[*index] = 0x80 | ((ch >> 12) & 0x3f);
    188                 (*index)++;
    189                 str[*index] = 0x80 | ((ch >> 6) & 0x3f);
    190                 (*index)++;
    191                 str[*index] = 0x80 | (ch & 0x3f);
    192                 return true;
    193         }
    194        
    195         return false;
     161
     162        if (ch < 0)
     163                return false;
     164
     165        /* Bit operations should only be done on unsigned numbers. */
     166        cc = (uint32_t) ch;
     167
     168        /* Determine how many continuation bytes are needed. */
     169        if ((cc & ~LO_MASK_32(7)) == 0) {
     170                b0_bits = 7;
     171                cbytes = 0;
     172        } else if ((cc & ~LO_MASK_32(11)) == 0) {
     173                b0_bits = 5;
     174                cbytes = 1;
     175        } else if ((cc & ~LO_MASK_32(16)) == 0) {
     176                b0_bits = 4;
     177                cbytes = 2;
     178        } else if ((cc & ~LO_MASK_32(21)) == 0) {
     179                b0_bits = 3;
     180                cbytes = 3;
     181        } else {
     182                /* Codes longer than 21 bits are not supported. */
     183                return false;
     184        }
     185
     186        /* Check for available space in buffer. */
     187        if (*index + cbytes > limit)
     188                return false;
     189
     190        /* Encode continuation bytes. */
     191        for (i = cbytes; i > 0; --i) {
     192                str[*index + i] = 0x80 | (cc & LO_MASK_32(CONT_BITS));
     193                cc = cc >> CONT_BITS;
     194        }
     195
     196        /* Encode first byte. */
     197        str[*index] = (cc & LO_MASK_32(b0_bits)) | HI_MASK_8(8 - b0_bits - 1);
     198
     199        /* Advance index. */
     200        *index += cbytes;
     201       
     202        return true;
    196203}
    197204
Note: See TracChangeset for help on using the changeset viewer.