windows-1251
Version:
A robust windows-1251 encoder/decoder written in JavaScript.
369 lines (358 loc) • 6.89 kB
JavaScript
/*! https://mths.be/windows-1251 v3.0.4 by @mathias | MIT license */
const stringFromCharCode = String.fromCharCode;
const INDEX_BY_CODE_POINT = new Map([
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[]
]);
const INDEX_BY_POINTER = new Map([
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[]
]);
// https://encoding.spec.whatwg.org/#error-mode
const decodingError = (mode) => {
if (mode === 'replacement') {
return '\uFFFD';
}
// Else, `mode == 'fatal'`.
throw new Error();
};
const encodingError = (mode) => {
if (mode === 'replacement') {
return 0xFFFD;
}
// Else, `mode == 'fatal'`.
throw new Error();
};
// https://encoding.spec.whatwg.org/#single-byte-decoder
export const decode = (input, options) => {
let mode;
if (options && options.mode) {
mode = options.mode.toLowerCase();
}
// “An error mode […] is either `replacement` (default) or `fatal` for a
// decoder.”
if (mode !== 'replacement' && mode !== 'fatal') {
mode = 'replacement';
}
const length = input.length;
// Support byte strings as input.
if (typeof input === 'string') {
const bytes = new Uint16Array(length);
for (let index = 0; index < length; index++) {
bytes[index] = input.charCodeAt(index);
}
input = bytes;
}
const buffer = [];
for (let index = 0; index < length; index++) {
const byteValue = input[index];
// “If `byte` is an ASCII byte, return a code point whose value is
// `byte`.”
if (0x00 <= byteValue && byteValue <= 0x7F) {
buffer.push(stringFromCharCode(byteValue));
continue;
}
// “Let `code point` be the index code point for `byte − 0x80` in index
// single-byte.”
const pointer = byteValue - 0x80;
if (INDEX_BY_POINTER.has(pointer)) {
// “Return a code point whose value is `code point`.”
buffer.push(INDEX_BY_POINTER.get(pointer));
} else {
// “If `code point` is `null`, return `error`.”
buffer.push(decodingError(mode));
}
}
const result = buffer.join('');
return result;
};
// https://encoding.spec.whatwg.org/#single-byte-encoder
export const encode = (input, options) => {
let mode;
if (options && options.mode) {
mode = options.mode.toLowerCase();
}
// Support `fatal` (default) and `replacement` error modes.
if (mode !== 'fatal' && mode !== 'replacement') {
mode = 'fatal';
}
const length = input.length;
const result = new Uint16Array(length);
for (let index = 0; index < length; index++) {
const codePoint = input.charCodeAt(index);
// “If `code point` is an ASCII code point, return a byte whose
// value is `code point`.”
if (0x00 <= codePoint && codePoint <= 0x7F) {
result[index] = codePoint;
continue;
}
// “Let `pointer` be the index pointer for `code point` in index
// single-byte.”
if (INDEX_BY_CODE_POINT.has(codePoint)) {
const pointer = INDEX_BY_CODE_POINT.get(codePoint);
// “Return a byte whose value is `pointer + 0x80`.”
result[index] = pointer + 0x80;
} else {
// “If `pointer` is `null`, return `error` with `code point`.”
result[index] = encodingError(mode);
}
}
return result;
};
export const labels = [
'cp1251',
'windows-1251',
'x-cp1251'
];