LINUX.ORG.RU

Unicode encoding


0

1

Всем привет, пытаюсь раскодировать Unicode, с русскими символами разобрался, получаю 0430 (а) и просто прибавля 0xCC80 и все работает, получаю d0b0, но как быть например с символом 다, получаю от wchar_t(ws = L"다") B2E4, но для раскодирования должно быть EB8BA4, в общем я могу конечно так же прибавить какую-то константу, но может есть более правильный способ? кодировка UTF-8

★★★

Google: ICU

anonymous
()
Ответ на: комментарий от anonymous

спасибо, почитаю, и почему сразу неуч, я вообще впервые с unicode столкнулся.

Int64 ★★★
() автор топика
Ответ на: комментарий от anonymous

очень хорошо описано, спасибо еще раз за ссылку!

Int64 ★★★
() автор топика

Когда мне потребовалось небольшое, легко встраиваемое решение, использовал http://utfcpp.sourceforge.net. Если есть необходимость обрабатывать вообще весь юникод и проводить операции над текстом (раскладка, переносы, изменение регистра), то лучше взять ICU. Но с ней сложно начинать.

note173 ★★★★★
()
Ответ на: комментарий от Int64

Если кому интересно, вот как сделал:

string EncodeUTF8(wchar_t uc) {
	string ret;
	Uint8 b1, b2, b3, b4, b5, b6;
	char c[3];
	
	//
	if ((uc > 0 & uc <= 0x007F) == 1) {
		ret += uc;
	} else if ((uc > 0x007F & uc <= 0x07FF) == 1) {
		b1 = 0xC0 | (uc & 0x7C0) >> 6;
		b2 = 0x80 | (uc & 0x3F);
		//
		ret  = b1;
		ret += b2;
		//
	} else if ((uc > 0x07FF & uc <= 0xFFFF) == 1) {
		b1 = 0xE0 | (uc & 0xF000) >> 12;
		b2 = 0x80 | (uc & 0xFC0) >> 6;
		b3 = 0x80 | (uc & 0x3F);
		//
		ret  = b1; ret += b2; ret += b3;
		//
	} else if ((uc > 0xFFFF & uc <= 0x1FFFFF) == 1) {
		b1 = 0xF0 | (uc & 0x1C00000) >> 18;
		b2 = 0x80 | (uc & 0x3F000) >> 12;
		b3 = 0x80 | (uc & 0xFC0) >> 6;
		b4 = 0x80 | (uc & 0x3F);
		//
		ret  = b1; ret += b2; ret += b3;
		ret += b4;
		//
	} else if ((uc > 0x1FFFFF & uc <= 0x3FFFFFF) == 1) {
		b1 = 0xF8 | (uc & 0x3000000) >> 24;
		b2 = 0x80 | (uc & 0xFC0000) >> 18;
		b3 = 0x80 | (uc & 0xF000) >> 12;
		b4 = 0x80 | (uc & 0xFC0) >> 6;
		b5 = 0x80 | (uc & 0x3F);
		//
		ret  = b1; ret += b2; ret += b3;
		ret += b4; ret += b5;
		//
	} else if ((uc > 0x3FFFFFF & uc <= 0x7FFFFFFF) == 1) {
		b1 = 0xFC | (uc & 0x40000000) >> 30;
		b2 = 0x80 | (uc & 0x3F000000) >> 24;
		b3 = 0x80 | (uc & 0xFC0000) >> 18;
		b4 = 0x80 | (uc & 0xF000) >> 12;
		b5 = 0x80 | (uc & 0xFC0) >> 6;
		b5 = 0x80 | (uc & 0x3F);
		//
		ret  = b1; ret += b2; ret += b3;
		ret += b4; ret += b5; ret += b6;
	}
	
	return ret;
}

string wstring2string(wstring ws, bool enter) {
	string s;
	
	// Unroll loop at 4 iterations
	int i;
	for (i = 0; i < ws.size()-(ws.size() >> 2); i += 4) {
		s += EncodeUTF8(ws[i+0]); s += EncodeUTF8(ws[i+1]);
		s += EncodeUTF8(ws[i+2]); s += EncodeUTF8(ws[i+3]);
	}
	
	//
	for (i; i < ws.size(); i++) {
		s += EncodeUTF8(ws[i]);
	}
	
	return s;
}

правда не проверял с 5ти байтовыми и 6ти байтовыми символами, если у кого есть

Int64 ★★★
() автор топика
Ответ на: комментарий от Int64

с 5ти байтовыми и 6ти байтовыми символами

Их в стандарте нет, так что код, отвечающий за декодирование 5/6-байтных последовательностей нужно выкинуть.

Впрочем, в твоей реализации есть еще несколько дырок.

https://tools.ietf.org/html/rfc3629

gatsu
()
Последнее исправление: gatsu (всего исправлений: 1)
Ответ на: комментарий от gatsu

ок убрал, а что еще за дырки? не до 0x1FFFFF а до 0x10FFFF?

Int64 ★★★
() автор топика
Ответ на: комментарий от gatsu

кажется понял, в безопасности дырки

Int64 ★★★
() автор топика
Ответ на: комментарий от gatsu

переписал так:

string EncodeUTF8(wchar_t uc) {
	string ret;
	Uint8 b1, b2, b3, b4, b5, b6;
	
	if (uc == 0x0040) return "";
	
	//
	if ((uc > 0x1 & uc <= 0x007F) == 1) {
		ret += uc;
		//
	} else if ((uc > 0x007F & uc <= 0x07FF) == 1) {
		b1 = 0xC0 | (uc & 0x7C0) >> 6;
		b2 = 0x80 | (uc & 0x3F);
		//
		ret  = b1;
		ret += b2;
		//
	} else if ((uc > 0x07FF & uc <= 0xFFFF) == 1) {
		b1 = 0xE0 | (uc & 0xF000) >> 12;
		b2 = 0x80 | (uc & 0xFC0) >> 6;
		b3 = 0x80 | (uc & 0x3F);
		//
		ret  = b1; ret += b2; ret += b3;
		//
	} else if ((uc > 0xFFFF & uc <= 0x10FFFF) == 1) {
		b1 = 0xF0 | (uc & 0x1C00000) >> 18;
		b2 = 0x80 | (uc & 0x3F000) >> 12;
		b3 = 0x80 | (uc & 0xFC0) >> 6;
		b4 = 0x80 | (uc & 0x3F);
		//
		ret  = b1; ret += b2; ret += b3;
		ret += b4;
		//
	}
	
	return ret;
}

Int64 ★★★
() автор топика
Ответ на: комментарий от Int64

А, ты же преобразуешь Unicode в UTF-8, тут всё элементарно.

Добавь игнорирование суррогатных пар UTF-16 (область 0xD800—0xDFFF).

https://github.com/gatsu/UTF8/blob/master/lib/utf8/base.php#L176

И вот это тебе может быть когда-нибудь пригодится: ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt

gatsu
()
Последнее исправление: gatsu (всего исправлений: 1)
Ответ на: комментарий от Int64

Так делать нельзя. wchar_t это компиляторозависимое представление символов, там может быть юникод, а может быть и неюникод.

Reset ★★★★★
()
Ответ на: комментарий от gatsu

спасибо большое, добавил игнор )

Int64 ★★★
() автор топика
Ответ на: комментарий от Reset

на другой компилятор я переходить вроде бы не собираюсь )

Int64 ★★★
() автор топика
        var result = '';
        var i = 0;
        var c, ucp;
        while (i < str.length) {
            c = str.charCodeAt(i);
            if (c <= 0x7f) {
                ucp = c;
            }
            else {
                var n;
                if ((c & 0xe0) == 0xc0) {
                    ucp = c & 0x1f;
                    n = 1;
                }
                else if ((c & 0xf0) == 0xe0) {
                    ucp = c & 0x0f;
                    n = 2;
                }
                else if ((c & 0xf8) == 0xf0) {
                    ucp = c & 7;
                    n = 3;
                }
                else {
                    return;
                }
                if (i >= str.length - n)
                    return;
                while (n--) {
                    c = str.charCodeAt(++i);
                    if ((c & 0xc0) != 0x80)
                        return;
                    ucp <<= 6;
                    ucp |= c & 0x3f;
                }
            }
            result += String.fromCharCode(ucp);
            i++;
        }
        return result;
anonymous
()
Ответ на: комментарий от anonymous

Тьфу, всё перепутал, надо же наоборот. Ну так там вообще делать нечего. Даже не буду код приводить.

anonymous
()
Ответ на: комментарий от Reset

wchar_t это компиляторозависимое представление символов, там может быть юникод, а может быть и неюникод.

А если у ТС в контексте использования его функции wchar_t uc всегда будет содержать юникод? Он же не указал, откуда поступают входные данные

annulen ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.