* Unicode 3.1 compliant validation : for each category, it checks the * combination of each byte to make sure it maps to a valid range. It also * returns -1 for the following UCS values: ucs > 0x10ffff ucs & 0xfffe = * 0xfffe 0xfdd0 < ucs < 0xfdef ucs & 0xdb00 = 0xd800 (surrogates) */
| 79 | * 0xfffe 0xfdd0 < ucs < 0xfdef ucs & 0xdb00 = 0xd800 (surrogates) |
| 80 | */ |
| 81 | static int |
| 82 | utf_charcheck(const unsigned char *c) |
| 83 | { |
| 84 | if ((*c & 0x80) == 0) |
| 85 | return 1; |
| 86 | else if ((*c & 0xe0) == 0xc0) |
| 87 | { |
| 88 | /* two-byte char */ |
| 89 | if (((c[1] & 0xc0) == 0x80) && ((c[0] & 0x1f) > 0x01)) |
| 90 | return 2; |
| 91 | return -1; |
| 92 | } |
| 93 | else if ((*c & 0xf0) == 0xe0) |
| 94 | { |
| 95 | /* three-byte char */ |
| 96 | if (((c[1] & 0xc0) == 0x80) && |
| 97 | (((c[0] & 0x0f) != 0x00) || ((c[1] & 0x20) == 0x20)) && |
| 98 | ((c[2] & 0xc0) == 0x80)) |
| 99 | { |
| 100 | int z = c[0] & 0x0f; |
| 101 | int yx = ((c[1] & 0x3f) << 6) | (c[0] & 0x3f); |
| 102 | int lx = yx & 0x7f; |
| 103 | |
| 104 | /* check 0xfffe/0xffff, 0xfdd0..0xfedf range, surrogates */ |
| 105 | if (((z == 0x0f) && |
| 106 | (((yx & 0xffe) == 0xffe) || |
| 107 | (((yx & 0xf80) == 0xd80) && (lx >= 0x30) && (lx <= 0x4f)))) || |
| 108 | ((z == 0x0d) && ((yx & 0xb00) == 0x800))) |
| 109 | return -1; |
| 110 | return 3; |
| 111 | } |
| 112 | return -1; |
| 113 | } |
| 114 | else if ((*c & 0xf8) == 0xf0) |
| 115 | { |
| 116 | int u = ((c[0] & 0x07) << 2) | ((c[1] & 0x30) >> 4); |
| 117 | |
| 118 | /* four-byte char */ |
| 119 | if (((c[1] & 0xc0) == 0x80) && |
| 120 | (u > 0x00) && (u <= 0x10) && |
| 121 | ((c[2] & 0xc0) == 0x80) && ((c[3] & 0xc0) == 0x80)) |
| 122 | { |
| 123 | /* test for 0xzzzzfffe/0xzzzzfffff */ |
| 124 | if (((c[1] & 0x0f) == 0x0f) && ((c[2] & 0x3f) == 0x3f) && |
| 125 | ((c[3] & 0x3e) == 0x3e)) |
| 126 | return -1; |
| 127 | return 4; |
| 128 | } |
| 129 | return -1; |
| 130 | } |
| 131 | return -1; |
| 132 | } |
| 133 | |
| 134 | |
| 135 | static void |