Changeset 0dd1d444 in mainline for kernel/generic/src/lib/string.c
- Timestamp:
- 2009-03-30T22:22:05Z (16 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 32704cb
- Parents:
- c18e666
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/lib/string.c
rc18e666 r0dd1d444 45 45 char invalch = '?'; 46 46 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 47 53 /** Decode a single UTF-8 character from a NULL-terminated string. 48 54 * … … 61 67 wchar_t utf8_decode(const char *str, index_t *index, index_t limit) 62 68 { 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 68 75 if (*index > limit) 69 76 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) { 81 116 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; 133 125 } 134 126
Note:
See TracChangeset
for help on using the changeset viewer.