• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1"use strict";
2
3var Buffer = require("buffer").Buffer,
4    Transform = require("stream").Transform;
5
6
7// == Exports ==================================================================
8module.exports = function(iconv) {
9
10    // Additional Public API.
11    iconv.encodeStream = function encodeStream(encoding, options) {
12        return new IconvLiteEncoderStream(iconv.getEncoder(encoding, options), options);
13    }
14
15    iconv.decodeStream = function decodeStream(encoding, options) {
16        return new IconvLiteDecoderStream(iconv.getDecoder(encoding, options), options);
17    }
18
19    iconv.supportsStreams = true;
20
21
22    // Not published yet.
23    iconv.IconvLiteEncoderStream = IconvLiteEncoderStream;
24    iconv.IconvLiteDecoderStream = IconvLiteDecoderStream;
25    iconv._collect = IconvLiteDecoderStream.prototype.collect;
26};
27
28
29// == Encoder stream =======================================================
30function IconvLiteEncoderStream(conv, options) {
31    this.conv = conv;
32    options = options || {};
33    options.decodeStrings = false; // We accept only strings, so we don't need to decode them.
34    Transform.call(this, options);
35}
36
37IconvLiteEncoderStream.prototype = Object.create(Transform.prototype, {
38    constructor: { value: IconvLiteEncoderStream }
39});
40
41IconvLiteEncoderStream.prototype._transform = function(chunk, encoding, done) {
42    if (typeof chunk != 'string')
43        return done(new Error("Iconv encoding stream needs strings as its input."));
44    try {
45        var res = this.conv.write(chunk);
46        if (res && res.length) this.push(res);
47        done();
48    }
49    catch (e) {
50        done(e);
51    }
52}
53
54IconvLiteEncoderStream.prototype._flush = function(done) {
55    try {
56        var res = this.conv.end();
57        if (res && res.length) this.push(res);
58        done();
59    }
60    catch (e) {
61        done(e);
62    }
63}
64
65IconvLiteEncoderStream.prototype.collect = function(cb) {
66    var chunks = [];
67    this.on('error', cb);
68    this.on('data', function(chunk) { chunks.push(chunk); });
69    this.on('end', function() {
70        cb(null, Buffer.concat(chunks));
71    });
72    return this;
73}
74
75
76// == Decoder stream =======================================================
77function IconvLiteDecoderStream(conv, options) {
78    this.conv = conv;
79    options = options || {};
80    options.encoding = this.encoding = 'utf8'; // We output strings.
81    Transform.call(this, options);
82}
83
84IconvLiteDecoderStream.prototype = Object.create(Transform.prototype, {
85    constructor: { value: IconvLiteDecoderStream }
86});
87
88IconvLiteDecoderStream.prototype._transform = function(chunk, encoding, done) {
89    if (!Buffer.isBuffer(chunk))
90        return done(new Error("Iconv decoding stream needs buffers as its input."));
91    try {
92        var res = this.conv.write(chunk);
93        if (res && res.length) this.push(res, this.encoding);
94        done();
95    }
96    catch (e) {
97        done(e);
98    }
99}
100
101IconvLiteDecoderStream.prototype._flush = function(done) {
102    try {
103        var res = this.conv.end();
104        if (res && res.length) this.push(res, this.encoding);
105        done();
106    }
107    catch (e) {
108        done(e);
109    }
110}
111
112IconvLiteDecoderStream.prototype.collect = function(cb) {
113    var res = '';
114    this.on('error', cb);
115    this.on('data', function(chunk) { res += chunk; });
116    this.on('end', function() {
117        cb(null, res);
118    });
119    return this;
120}
121
122