All files / src/encodings utf8js.ts

100% Statements 50/50
100% Branches 14/14
100% Functions 2/2
100% Lines 49/49

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83    14x   34084x 34083x 259229x 259229x   239091x 239087x 20138x     2731x 2731x 2731x 2731x 17407x     14420x 14420x 14420x 14420x 14420x   2987x     2987x 2987x 2987x 2987x 2987x 2986x         20598x 20598x 20598x 159896x 159896x   146176x 146176x 13720x       2090x 2090x 2090x 11630x         9812x 9812x 9812x 9812x             1818x 1818x 1818x 1818x 1818x 1818x 1818x     20598x      
import { Encoding } from "../types";
 
export const utf8js: Encoding<string> = {
  encode(ctx, data) {
    const { length } = data;
    for (let i = 0; i < length; i++) {
      const code = data.charCodeAt(i) as number;
      if (code < 0x80) {
        // 0xxxxxxx
        ctx.view.setUint8(ctx.i, code);
        ctx.i++;
      } else if (code < 0x800) {
        // .... .aaa - aabb bbbb
        // 110a aaaa - 10bb bbbb
        const a = (code & 0x7c0) << 2;
        const b = code & 0x3f;
        ctx.view.setUint16(ctx.i, a | b | 0xc080);
        ctx.i += 2;
      } else if (code < 0xd800 || code >= 0xe000) {
        // .... .... - .... .... - aaaa bbbb - bbcc cccc
        // 1110 aaaa - 10bb bbbb - 10cc cccc - .... ....
        const a = (code & 0xf000) << 12;
        const b = (code & 0xfc0) << 10;
        const c = (code & 0x3f) << 8;
        ctx.view.setUint32(ctx.i, a | b | c | 0xe0808000);
        ctx.i += 3;
      } else {
        const code = data.codePointAt(i++) as number;
        // .... .... - .... aabb - bbbb cccc - ccdd dddd
        // 1111 00aa - 10bb bbbb - 10cc cccc - 10dd dddd
        const a = (code & 0x1c0000) << 6;
        const b = (code & 0x3f000) << 4;
        const c = (code & 0xfc0) << 2;
        const d = code & 0x3f;
        ctx.view.setUint32(ctx.i, a | b | c | d | 0xf0808080);
        ctx.i += 4;
      }
    }
  },
  decode(ctx, size) {
    const codes: number[] = [];
    const end = ctx.i + size;
    while (ctx.i < end) {
      const s = ctx.view.getUint8(ctx.i);
      if (s < 192) {
        // 0xxxxxxx
        codes.push(s);
        ctx.i++;
      } else if (s < 224) {
        //     110a aaaa
        //     10bb bbbb
        // aaa aabb bbbb
        const b = ctx.view.getUint8(ctx.i + 1);
        ctx.i += 2;
        codes.push(((s & 0x1f) << 6) | (b & 0x3f));
      } else if (s < 240) {
        //           1110 aaaa
        //           10bb bbbb
        //           10cc cccc
        // aaaa bbbb bbcc cccc
        const b = ctx.view.getUint8(ctx.i + 1);
        const c = ctx.view.getUint8(ctx.i + 2);
        ctx.i += 3;
        codes.push(
          ((s & 0x0f) << 12) | ((b & 0x3f) << 6) | (c & 0x3f)
        );
      } else {
        // 1111 0aaa, 10bb bbbb, 10cc cccc, 10dd dddd
        //               a aabb, bbbb cccc, ccdd dddd
 
        const u = ctx.view.getUint32(ctx.i);
        const a = (s & 0x7) << 18;
        const b = (u & 0x3f0000) >> 4;
        const c = (u & 0x3f00) >> 2;
        const d = u & 0x3f;
        codes.push(a | b | c | d);
        ctx.i += 4;
      }
    }
    return String.fromCodePoint(...codes);
  }
};