3 // == Extend Node primitives to use iconv-lite =================================
5 module.exports = function (iconv) {
6 var original = undefined; // Place to keep original methods.
8 // Node authors rewrote Buffer internals to make it compatible with
9 // Uint8Array and we cannot patch key functions since then.
10 iconv.supportsNodeEncodingsExtension = !(new Buffer(0) instanceof Uint8Array);
12 iconv.extendNodeEncodings = function extendNodeEncodings() {
16 if (!iconv.supportsNodeEncodingsExtension) {
17 console.error("ACTION NEEDED: require('iconv-lite').extendNodeEncodings() is not supported in your version of Node");
18 console.error("See more info at https://github.com/ashtuchkin/iconv-lite/wiki/Node-v4-compatibility");
22 var nodeNativeEncodings = {
23 'hex': true, 'utf8': true, 'utf-8': true, 'ascii': true, 'binary': true,
24 'base64': true, 'ucs2': true, 'ucs-2': true, 'utf16le': true, 'utf-16le': true,
27 Buffer.isNativeEncoding = function(enc) {
28 return enc && nodeNativeEncodings[enc.toLowerCase()];
31 // -- SlowBuffer -----------------------------------------------------------
32 var SlowBuffer = require('buffer').SlowBuffer;
34 original.SlowBufferToString = SlowBuffer.prototype.toString;
35 SlowBuffer.prototype.toString = function(encoding, start, end) {
36 encoding = String(encoding || 'utf8').toLowerCase();
38 // Use native conversion when possible
39 if (Buffer.isNativeEncoding(encoding))
40 return original.SlowBufferToString.call(this, encoding, start, end);
42 // Otherwise, use our decoding method.
43 if (typeof start == 'undefined') start = 0;
44 if (typeof end == 'undefined') end = this.length;
45 return iconv.decode(this.slice(start, end), encoding);
48 original.SlowBufferWrite = SlowBuffer.prototype.write;
49 SlowBuffer.prototype.write = function(string, offset, length, encoding) {
50 // Support both (string, offset, length, encoding)
51 // and the legacy (string, encoding, offset, length)
52 if (isFinite(offset)) {
53 if (!isFinite(length)) {
64 offset = +offset || 0;
65 var remaining = this.length - offset;
70 if (length > remaining) {
74 encoding = String(encoding || 'utf8').toLowerCase();
76 // Use native conversion when possible
77 if (Buffer.isNativeEncoding(encoding))
78 return original.SlowBufferWrite.call(this, string, offset, length, encoding);
80 if (string.length > 0 && (length < 0 || offset < 0))
81 throw new RangeError('attempt to write beyond buffer bounds');
83 // Otherwise, use our encoding method.
84 var buf = iconv.encode(string, encoding);
85 if (buf.length < length) length = buf.length;
86 buf.copy(this, offset, 0, length);
90 // -- Buffer ---------------------------------------------------------------
92 original.BufferIsEncoding = Buffer.isEncoding;
93 Buffer.isEncoding = function(encoding) {
94 return Buffer.isNativeEncoding(encoding) || iconv.encodingExists(encoding);
97 original.BufferByteLength = Buffer.byteLength;
98 Buffer.byteLength = SlowBuffer.byteLength = function(str, encoding) {
99 encoding = String(encoding || 'utf8').toLowerCase();
101 // Use native conversion when possible
102 if (Buffer.isNativeEncoding(encoding))
103 return original.BufferByteLength.call(this, str, encoding);
105 // Slow, I know, but we don't have a better way yet.
106 return iconv.encode(str, encoding).length;
109 original.BufferToString = Buffer.prototype.toString;
110 Buffer.prototype.toString = function(encoding, start, end) {
111 encoding = String(encoding || 'utf8').toLowerCase();
113 // Use native conversion when possible
114 if (Buffer.isNativeEncoding(encoding))
115 return original.BufferToString.call(this, encoding, start, end);
117 // Otherwise, use our decoding method.
118 if (typeof start == 'undefined') start = 0;
119 if (typeof end == 'undefined') end = this.length;
120 return iconv.decode(this.slice(start, end), encoding);
123 original.BufferWrite = Buffer.prototype.write;
124 Buffer.prototype.write = function(string, offset, length, encoding) {
125 var _offset = offset, _length = length, _encoding = encoding;
126 // Support both (string, offset, length, encoding)
127 // and the legacy (string, encoding, offset, length)
128 if (isFinite(offset)) {
129 if (!isFinite(length)) {
140 encoding = String(encoding || 'utf8').toLowerCase();
142 // Use native conversion when possible
143 if (Buffer.isNativeEncoding(encoding))
144 return original.BufferWrite.call(this, string, _offset, _length, _encoding);
146 offset = +offset || 0;
147 var remaining = this.length - offset;
152 if (length > remaining) {
157 if (string.length > 0 && (length < 0 || offset < 0))
158 throw new RangeError('attempt to write beyond buffer bounds');
160 // Otherwise, use our encoding method.
161 var buf = iconv.encode(string, encoding);
162 if (buf.length < length) length = buf.length;
163 buf.copy(this, offset, 0, length);
166 // TODO: Set _charsWritten.
170 // -- Readable -------------------------------------------------------------
171 if (iconv.supportsStreams) {
172 var Readable = require('stream').Readable;
174 original.ReadableSetEncoding = Readable.prototype.setEncoding;
175 Readable.prototype.setEncoding = function setEncoding(enc, options) {
176 // Use our own decoder, it has the same interface.
177 // We cannot use original function as it doesn't handle BOM-s.
178 this._readableState.decoder = iconv.getDecoder(enc, options);
179 this._readableState.encoding = enc;
182 Readable.prototype.collect = iconv._collect;
186 // Remove iconv-lite Node primitive extensions.
187 iconv.undoExtendNodeEncodings = function undoExtendNodeEncodings() {
188 if (!iconv.supportsNodeEncodingsExtension)
191 throw new Error("require('iconv-lite').undoExtendNodeEncodings(): Nothing to undo; extendNodeEncodings() is not called.")
193 delete Buffer.isNativeEncoding;
195 var SlowBuffer = require('buffer').SlowBuffer;
197 SlowBuffer.prototype.toString = original.SlowBufferToString;
198 SlowBuffer.prototype.write = original.SlowBufferWrite;
200 Buffer.isEncoding = original.BufferIsEncoding;
201 Buffer.byteLength = original.BufferByteLength;
202 Buffer.prototype.toString = original.BufferToString;
203 Buffer.prototype.write = original.BufferWrite;
205 if (iconv.supportsStreams) {
206 var Readable = require('stream').Readable;
208 Readable.prototype.setEncoding = original.ReadableSetEncoding;
209 delete Readable.prototype.collect;
212 original = undefined;