internal.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. "use strict"
  2. // Export Node.js internal encodings.
  3. module.exports = {
  4. // Encodings
  5. utf8: { type: "_internal", bomAware: true},
  6. cesu8: { type: "_internal", bomAware: true},
  7. unicode11utf8: "utf8",
  8. ucs2: { type: "_internal", bomAware: true},
  9. utf16le: "ucs2",
  10. binary: { type: "_internal" },
  11. base64: { type: "_internal" },
  12. hex: { type: "_internal" },
  13. // Codec.
  14. _internal: InternalCodec,
  15. };
  16. //------------------------------------------------------------------------------
  17. function InternalCodec(codecOptions) {
  18. this.enc = codecOptions.encodingName;
  19. this.bomAware = codecOptions.bomAware;
  20. if (this.enc === "base64")
  21. this.encoder = InternalEncoderBase64;
  22. else if (this.enc === "cesu8") {
  23. this.enc = "utf8"; // Use utf8 for decoding.
  24. this.encoder = InternalEncoderCesu8;
  25. }
  26. }
  27. InternalCodec.prototype.encoder = InternalEncoder;
  28. InternalCodec.prototype.decoder = InternalDecoder;
  29. //------------------------------------------------------------------------------
  30. // We use node.js internal decoder. It's signature is the same as ours.
  31. var StringDecoder = require('string_decoder').StringDecoder;
  32. if (!StringDecoder.prototype.end) // Node v0.8 doesn't have this method.
  33. StringDecoder.prototype.end = function() {};
  34. function InternalDecoder(options, codec) {
  35. StringDecoder.call(this, codec.enc);
  36. }
  37. InternalDecoder.prototype = StringDecoder.prototype;
  38. //------------------------------------------------------------------------------
  39. // Encoder is mostly trivial
  40. function InternalEncoder(options, codec) {
  41. this.enc = codec.enc;
  42. }
  43. InternalEncoder.prototype.write = function(str) {
  44. return new Buffer(str, this.enc);
  45. }
  46. InternalEncoder.prototype.end = function() {
  47. }
  48. //------------------------------------------------------------------------------
  49. // Except base64 encoder, which must keep its state.
  50. function InternalEncoderBase64(options, codec) {
  51. this.prevStr = '';
  52. }
  53. InternalEncoderBase64.prototype.write = function(str) {
  54. str = this.prevStr + str;
  55. var completeQuads = str.length - (str.length % 4);
  56. this.prevStr = str.slice(completeQuads);
  57. str = str.slice(0, completeQuads);
  58. return new Buffer(str, "base64");
  59. }
  60. InternalEncoderBase64.prototype.end = function() {
  61. return new Buffer(this.prevStr, "base64");
  62. }
  63. //------------------------------------------------------------------------------
  64. // CESU-8 encoder is also special.
  65. function InternalEncoderCesu8(options, codec) {
  66. }
  67. InternalEncoderCesu8.prototype.write = function(str) {
  68. var buf = new Buffer(str.length * 3), bufIdx = 0;
  69. for (var i = 0; i < str.length; i++) {
  70. var charCode = str.charCodeAt(i);
  71. // Naive implementation, but it works because CESU-8 is especially easy
  72. // to convert from UTF-16 (which all JS strings are encoded in).
  73. if (charCode < 0x80)
  74. buf[bufIdx++] = charCode;
  75. else if (charCode < 0x800) {
  76. buf[bufIdx++] = 0xC0 + (charCode >>> 6);
  77. buf[bufIdx++] = 0x80 + (charCode & 0x3f);
  78. }
  79. else { // charCode will always be < 0x10000 in javascript.
  80. buf[bufIdx++] = 0xE0 + (charCode >>> 12);
  81. buf[bufIdx++] = 0x80 + ((charCode >>> 6) & 0x3f);
  82. buf[bufIdx++] = 0x80 + (charCode & 0x3f);
  83. }
  84. }
  85. return buf.slice(0, bufIdx);
  86. }
  87. InternalEncoderCesu8.prototype.end = function() {
  88. }