Big5Decoder.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. import { decoderError } from "../../encoding/encodings";
  2. import { finished } from "../../encoding/finished";
  3. import { index, indexCodePointFor } from "../../encoding/indexes";
  4. import { end_of_stream, isASCIIByte } from "../../encoding/terminology";
  5. import { inRange } from "../../encoding/utilities";
  6. /**
  7. * @constructor
  8. * @implements {Decoder}
  9. * @param {{fatal: boolean}} options
  10. */
  11. export class Big5Decoder {
  12. constructor(options) {
  13. this.fatal = options.fatal;
  14. // Big5's decoder has an associated Big5 lead (initially 0x00).
  15. /** @type {number} */ this.Big5_lead = 0x00;
  16. }
  17. /**
  18. * @param {Stream} stream The stream of bytes being decoded.
  19. * @param {number} bite The next byte read from the stream.
  20. * @return {?(number|!Array.<number>)} The next code point(s)
  21. * decoded, or null if not enough data exists in the input
  22. * stream to decode a complete code point.
  23. */
  24. handler(stream, bite) {
  25. // 1. If byte is end-of-stream and Big5 lead is not 0x00, set
  26. // Big5 lead to 0x00 and return error.
  27. if (bite === end_of_stream && this.Big5_lead !== 0x00) {
  28. this.Big5_lead = 0x00;
  29. return decoderError(this.fatal);
  30. }
  31. // 2. If byte is end-of-stream and Big5 lead is 0x00, return
  32. // finished.
  33. if (bite === end_of_stream && this.Big5_lead === 0x00)
  34. return finished;
  35. // 3. If Big5 lead is not 0x00, let lead be Big5 lead, let
  36. // pointer be null, set Big5 lead to 0x00, and then run these
  37. // substeps:
  38. if (this.Big5_lead !== 0x00) {
  39. const lead = this.Big5_lead;
  40. let pointer = null;
  41. this.Big5_lead = 0x00;
  42. // 1. Let offset be 0x40 if byte is less than 0x7F and 0x62
  43. // otherwise.
  44. const offset = bite < 0x7F ? 0x40 : 0x62;
  45. // 2. If byte is in the range 0x40 to 0x7E, inclusive, or 0xA1
  46. // to 0xFE, inclusive, set pointer to (lead − 0x81) × 157 +
  47. // (byte − offset).
  48. if (inRange(bite, 0x40, 0x7E) || inRange(bite, 0xA1, 0xFE))
  49. pointer = (lead - 0x81) * 157 + (bite - offset);
  50. // 3. If there is a row in the table below whose first column
  51. // is pointer, return the two code points listed in its second
  52. // column
  53. // Pointer | Code points
  54. // --------+--------------
  55. // 1133 | U+00CA U+0304
  56. // 1135 | U+00CA U+030C
  57. // 1164 | U+00EA U+0304
  58. // 1166 | U+00EA U+030C
  59. switch (pointer) {
  60. case 1133: return [0x00CA, 0x0304];
  61. case 1135: return [0x00CA, 0x030C];
  62. case 1164: return [0x00EA, 0x0304];
  63. case 1166: return [0x00EA, 0x030C];
  64. }
  65. // 4. Let code point be null if pointer is null and the index
  66. // code point for pointer in index Big5 otherwise.
  67. const code_point = (pointer === null) ? null :
  68. indexCodePointFor(pointer, index('big5'));
  69. // 5. If code point is null and byte is an ASCII byte, prepend
  70. // byte to stream.
  71. if (code_point === null && isASCIIByte(bite))
  72. stream.prepend(bite);
  73. // 6. If code point is null, return error.
  74. if (code_point === null)
  75. return decoderError(this.fatal);
  76. // 7. Return a code point whose value is code point.
  77. return code_point;
  78. }
  79. // 4. If byte is an ASCII byte, return a code point whose value
  80. // is byte.
  81. if (isASCIIByte(bite))
  82. return bite;
  83. // 5. If byte is in the range 0x81 to 0xFE, inclusive, set Big5
  84. // lead to byte and return continue.
  85. if (inRange(bite, 0x81, 0xFE)) {
  86. this.Big5_lead = bite;
  87. return null;
  88. }
  89. // 6. Return error.
  90. return decoderError(this.fatal);
  91. }
  92. }
  93. //# sourceMappingURL=Big5Decoder.js.map