Примечание: если вы следили за моими недавними вопросами, вы увидите, что все они касаются моего упражнения с библиотекой Unicode в C - как одного из моих первых нескольких серьезных проектов в C, у меня много проблем, так что извините, если я задаю слишком много вопросов об одной вещи.
Часть моей библиотеки декодирует кодированные в UTF-8 char
указатели в необработанные unsigned
кодовые точки. Тем не менее, некоторые самолеты не декодируют правильно. Давайте посмотрим на (соответствующий) код:
typedef struct string {
unsigned long length;
unsigned *data;
} string;
// really simple stuff
string *upush(string *s, unsigned c) {
if (!s->length) s->data = (unsigned *) malloc((s->length = 1) * sizeof(unsigned));
else s->data = (unsigned *) realloc(s->data, ++s->length * sizeof(unsigned));
s->data[s->length - 1] = c;
return s;
}
// UTF-8 conversions
string ctou(char *old) {
unsigned long i, byte = 0, cur = 0;
string new;
new.length = 0;
for (i = 0; old[i]; i++)
if (old[i] < 0x80) upush(&new, old[i]);
else if (old[i] < 0xc0)
if (!byte) {
byte = cur = 0;
continue;
} else {
cur |= (unsigned)(old[i] & 0x3f) << (6 * (--byte));
if (!byte) upush(&new, cur), cur = 0;
}
else if (old[i] < 0xc2) continue;
else if (old[i] < 0xe0) {
cur = (unsigned)(old[i] & 0x1f) << 6;
byte = 1;
}
else if (old[i] < 0xf0) {
cur = (unsigned)(old[i] & 0xf) << 12;
byte = 2;
}
else if (old[i] < 0xf5) {
cur = (unsigned)(old[i] & 0x7) << 18;
byte = 3;
}
else continue;
return new;
}
Все, что upush
делает, кстати, помещает кодовую точку в конец string
, перераспределяя память по мере необходимости. ctou
выполняет декодирование и сохраняет количество байтов, все еще необходимое в последовательности, в byte
, а также код выполняемой точки в cur
.
Код кажется мне правильным. Давайте попробуем расшифровать U+10ffff
, то есть f4 8f bf bd
в UTF-8. Делаем это:
long i;
string b = ctou("\xf4\x8f\xbf\xbd");
for (i = 0; i < b.length; i++)
printf("%z ", b.data[i]);
должен распечатать:
10ffff
но вместо этого он печатает:
fffffff4 ffffff8f ffffffbf ffffffbd
, который в основном является четырьмя байтами UTF-8, с ffffff
, прикрепленным перед ним.
Любое руководство о том, что не так в моем коде?