Я смотрю на это :
function encodeCodePoint(codePoint) {
if ((codePoint & 0xFFFFFF80) == 0) { // 1-byte sequence
return stringFromCharCode(codePoint);
}
var symbol = '';
if ((codePoint & 0xFFFFF800) == 0) { // 2-byte sequence
symbol = stringFromCharCode(((codePoint >> 6) & 0x1F) | 0xC0);
}
else if ((codePoint & 0xFFFF0000) == 0) { // 3-byte sequence
checkScalarValue(codePoint);
symbol = stringFromCharCode(((codePoint >> 12) & 0x0F) | 0xE0);
symbol += createByte(codePoint, 6);
}
else if ((codePoint & 0xFFE00000) == 0) { // 4-byte sequence
symbol = stringFromCharCode(((codePoint >> 18) & 0x07) | 0xF0);
symbol += createByte(codePoint, 12);
symbol += createByte(codePoint, 6);
}
symbol += stringFromCharCode((codePoint & 0x3F) | 0x80);
return symbol;
}
, которое в JavaScript, кажется, использует тот факт, что числа в JavaScript (я думаю) что-то около 32длинойТаким образом, он выполняет некоторые битовые манипуляции, с которыми я не знаком, и получает закодированное значение. То же самое с функцией decode
:
function decodeSymbol() {
var byte1;
var byte2;
var byte3;
var byte4;
var codePoint;
if (byteIndex > byteCount) {
throw Error('Invalid byte index');
}
if (byteIndex == byteCount) {
return false;
}
// Read first byte
byte1 = byteArray[byteIndex] & 0xFF;
byteIndex++;
// 1-byte sequence (no continuation bytes)
if ((byte1 & 0x80) == 0) {
return byte1;
}
// 2-byte sequence
if ((byte1 & 0xE0) == 0xC0) {
byte2 = readContinuationByte();
codePoint = ((byte1 & 0x1F) << 6) | byte2;
if (codePoint >= 0x80) {
return codePoint;
} else {
throw Error('Invalid continuation byte');
}
}
// 3-byte sequence (may include unpaired surrogates)
if ((byte1 & 0xF0) == 0xE0) {
byte2 = readContinuationByte();
byte3 = readContinuationByte();
codePoint = ((byte1 & 0x0F) << 12) | (byte2 << 6) | byte3;
if (codePoint >= 0x0800) {
checkScalarValue(codePoint);
return codePoint;
} else {
throw Error('Invalid continuation byte');
}
}
// 4-byte sequence
if ((byte1 & 0xF8) == 0xF0) {
byte2 = readContinuationByte();
byte3 = readContinuationByte();
byte4 = readContinuationByte();
codePoint = ((byte1 & 0x07) << 0x12) | (byte2 << 0x0C) |
(byte3 << 0x06) | byte4;
if (codePoint >= 0x010000 && codePoint <= 0x10FFFF) {
return codePoint;
}
}
throw Error('Invalid UTF-8 detected');
}
По сути, я не совсем читаю этот код и не могу точно сказать, что происходит. Интересно, может ли тот, кто лучше разбирается в битовых манипуляциях или обладает знаниями в области кодирования UTF-8, мог бы на высоком уровне описать, что является входом и выходом от кодирования и декодирования, и очень примерно, как он идет от входа к выходу для каждого,Я пытаюсь создать кодировщик / декодер utf-8 и не вижу точно, как 8-битный поток разбивается на куски от 1 до 4 байтов, отчасти потому, что, как мне кажется, мешает 32-битное целое число JavaScript. Но мне кажется, что вот что происходит:
Декодирование:
- У нас есть 8-битный (1-байтовый) поток данных.
- Мыполучить байт
- Мы проверяем, находится ли этот байт в каком-то определенном диапазоне (чего я не знаю)
- Если он находится в некотором диапазоне, то мы знаем, что следует дополнительный байт,или что-то в этом роде.
- Затем мы собираем все байты для символа ...
- И в случае с JavaScript конвертируем его в целое число, а затем
String.fromCharCode(integer)
.
Чего мне не хватает, так это того, как именно он идет от 1-байтовой последовательности до 4-х байтов, как он выполняет эту часть?
Кодировка:
- Это зависит от языка / архитектуры, так как некоторые архитектуры будут иметь целые числа 16, 32 или 64 бита (... я предполагаю ...).
- В случае JavaScriptвозьмите 32-разрядное целое число и выполните магию манипуляции с битами, чтобы извлечь от 1 до 4 байт для этого символа. Откуда он знает, сколько байтов получить ???
- Повторяйте, пока у вас не будет массива байтов.
Интересно, можно ли заполнить пробелы в моем понимании. Я не ищу точно каждый шаг бит-манипуляции, так как их много. Я просто ищу вопросы, которые я выделил в своем анализе чуть выше.