Decoder.js 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. 'use strict'
  2. const RE_PLUS = /\+/g
  3. const HEX = [
  4. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  5. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  6. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  7. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
  8. 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  9. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  10. 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  11. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  12. ]
  13. function Decoder () {
  14. this.buffer = undefined
  15. }
  16. Decoder.prototype.write = function (str) {
  17. // Replace '+' with ' ' before decoding
  18. str = str.replace(RE_PLUS, ' ')
  19. let res = ''
  20. let i = 0; let p = 0; const len = str.length
  21. for (; i < len; ++i) {
  22. if (this.buffer !== undefined) {
  23. if (!HEX[str.charCodeAt(i)]) {
  24. res += '%' + this.buffer
  25. this.buffer = undefined
  26. --i // retry character
  27. } else {
  28. this.buffer += str[i]
  29. ++p
  30. if (this.buffer.length === 2) {
  31. res += String.fromCharCode(parseInt(this.buffer, 16))
  32. this.buffer = undefined
  33. }
  34. }
  35. } else if (str[i] === '%') {
  36. if (i > p) {
  37. res += str.substring(p, i)
  38. p = i
  39. }
  40. this.buffer = ''
  41. ++p
  42. }
  43. }
  44. if (p < len && this.buffer === undefined) { res += str.substring(p) }
  45. return res
  46. }
  47. Decoder.prototype.reset = function () {
  48. this.buffer = undefined
  49. }
  50. module.exports = Decoder