- o = (uint8_t*) output;
- for (p = (const uint8_t*) str; *p; p++) {
- if (*p < 128) {
- if (o)
- *o = *p;
- } else {
- last = p;
-
- if ((*p & 0xe0) == 0xc0) { /* 110xxxxx two-char seq. */
- size = 2;
- min = 128;
- val = (uint32_t) (*p & 0x1e);
- goto ONE_REMAINING;
- } else if ((*p & 0xf0) == 0xe0) { /* 1110xxxx three-char seq.*/
- size = 3;
- min = (1 << 11);
- val = (uint32_t) (*p & 0x0f);
- goto TWO_REMAINING;
- } else if ((*p & 0xf8) == 0xf0) { /* 11110xxx four-char seq */
- size = 4;
- min = (1 << 16);
- val = (uint32_t) (*p & 0x07);
- } else
- goto error;
-
- p++;
- if (!is_continuation_char(*p))
- goto error;
- merge_continuation_char(&val, *p);
-
- TWO_REMAINING:
- p++;
- if (!is_continuation_char(*p))
- goto error;
- merge_continuation_char(&val, *p);
-
- ONE_REMAINING:
- p++;
- if (!is_continuation_char(*p))
- goto error;
- merge_continuation_char(&val, *p);
-
- if (val < min)
- goto error;
-
- if (!is_unicode_valid(val))
- goto error;
-
- if (o) {
- memcpy(o, last, (size_t) size);
- o += size;
- }
-
- continue;
-
- error:
- if (o) {
- *o = FILTER_CHAR;
- p = last; /* We retry at the next character */
- } else
- goto failure;
- }
+ c = (unsigned char) str[0];
+ if (c < 0x80)
+ return 1;
+ if ((c & 0xe0) == 0xc0)
+ return 2;
+ if ((c & 0xf0) == 0xe0)
+ return 3;
+ if ((c & 0xf8) == 0xf0)
+ return 4;
+ if ((c & 0xfc) == 0xf8)
+ return 5;
+ if ((c & 0xfe) == 0xfc)
+ return 6;
+
+ return 0;
+}