3 // == Extend Node primitives to use iconv-lite =================================
5 module.exports = function (iconv) {
6 var original = undefined; // Place to keep original methods.
8 iconv.extendNodeEncodings = function extendNodeEncodings() {
12 var nodeNativeEncodings = {
13 'hex': true, 'utf8': true, 'utf-8': true, 'ascii': true, 'binary': true,
14 'base64': true, 'ucs2': true, 'ucs-2': true, 'utf16le': true, 'utf-16le': true,
17 Buffer.isNativeEncoding = function(enc) {
18 return enc && nodeNativeEncodings[enc.toLowerCase()];
21 // -- SlowBuffer -----------------------------------------------------------
22 var SlowBuffer = require('buffer').SlowBuffer;
24 original.SlowBufferToString = SlowBuffer.prototype.toString;
25 SlowBuffer.prototype.toString = function(encoding, start, end) {
26 encoding = String(encoding || 'utf8').toLowerCase();
28 // Use native conversion when possible
29 if (Buffer.isNativeEncoding(encoding))
30 return original.SlowBufferToString.call(this, encoding, start, end);
32 // Otherwise, use our decoding method.
33 if (typeof start == 'undefined') start = 0;
34 if (typeof end == 'undefined') end = this.length;
35 return iconv.decode(this.slice(start, end), encoding);
38 original.SlowBufferWrite = SlowBuffer.prototype.write;
39 SlowBuffer.prototype.write = function(string, offset, length, encoding) {
40 // Support both (string, offset, length, encoding)
41 // and the legacy (string, encoding, offset, length)
42 if (isFinite(offset)) {
43 if (!isFinite(length)) {
54 offset = +offset || 0;
55 var remaining = this.length - offset;
60 if (length > remaining) {
64 encoding = String(encoding || 'utf8').toLowerCase();
66 // Use native conversion when possible
67 if (Buffer.isNativeEncoding(encoding))
68 return original.SlowBufferWrite.call(this, string, offset, length, encoding);
70 if (string.length > 0 && (length < 0 || offset < 0))
71 throw new RangeError('attempt to write beyond buffer bounds');
73 // Otherwise, use our encoding method.
74 var buf = iconv.encode(string, encoding);
75 if (buf.length < length) length = buf.length;
76 buf.copy(this, offset, 0, length);
80 // -- Buffer ---------------------------------------------------------------
82 original.BufferIsEncoding = Buffer.isEncoding;
83 Buffer.isEncoding = function(encoding) {
84 return Buffer.isNativeEncoding(encoding) || iconv.encodingExists(encoding);
87 original.BufferByteLength = Buffer.byteLength;
88 Buffer.byteLength = SlowBuffer.byteLength = function(str, encoding) {
89 encoding = String(encoding || 'utf8').toLowerCase();
91 // Use native conversion when possible
92 if (Buffer.isNativeEncoding(encoding))
93 return original.BufferByteLength.call(this, str, encoding);
95 // Slow, I know, but we don't have a better way yet.
96 return iconv.encode(str, encoding).length;
99 original.BufferToString = Buffer.prototype.toString;
100 Buffer.prototype.toString = function(encoding, start, end) {
101 encoding = String(encoding || 'utf8').toLowerCase();
103 // Use native conversion when possible
104 if (Buffer.isNativeEncoding(encoding))
105 return original.BufferToString.call(this, encoding, start, end);
107 // Otherwise, use our decoding method.
108 if (typeof start == 'undefined') start = 0;
109 if (typeof end == 'undefined') end = this.length;
110 return iconv.decode(this.slice(start, end), encoding);
113 original.BufferWrite = Buffer.prototype.write;
114 Buffer.prototype.write = function(string, offset, length, encoding) {
115 var _offset = offset, _length = length, _encoding = encoding;
116 // Support both (string, offset, length, encoding)
117 // and the legacy (string, encoding, offset, length)
118 if (isFinite(offset)) {
119 if (!isFinite(length)) {
130 encoding = String(encoding || 'utf8').toLowerCase();
132 // Use native conversion when possible
133 if (Buffer.isNativeEncoding(encoding))
134 return original.BufferWrite.call(this, string, _offset, _length, _encoding);
136 offset = +offset || 0;
137 var remaining = this.length - offset;
142 if (length > remaining) {
147 if (string.length > 0 && (length < 0 || offset < 0))
148 throw new RangeError('attempt to write beyond buffer bounds');
150 // Otherwise, use our encoding method.
151 var buf = iconv.encode(string, encoding);
152 if (buf.length < length) length = buf.length;
153 buf.copy(this, offset, 0, length);
156 // TODO: Set _charsWritten.
160 // -- Readable -------------------------------------------------------------
161 if (iconv.supportsStreams) {
162 var Readable = require('stream').Readable;
164 original.ReadableSetEncoding = Readable.prototype.setEncoding;
165 Readable.prototype.setEncoding = function setEncoding(enc, options) {
166 // Use our own decoder, it has the same interface.
167 // We cannot use original function as it doesn't handle BOM-s.
168 this._readableState.decoder = iconv.getDecoder(enc, options);
169 this._readableState.encoding = enc;
172 Readable.prototype.collect = iconv._collect;
176 // Remove iconv-lite Node primitive extensions.
177 iconv.undoExtendNodeEncodings = function undoExtendNodeEncodings() {
179 throw new Error("require('iconv-lite').undoExtendNodeEncodings(): Nothing to undo; extendNodeEncodings() is not called.")
181 delete Buffer.isNativeEncoding;
183 var SlowBuffer = require('buffer').SlowBuffer;
185 SlowBuffer.prototype.toString = original.SlowBufferToString;
186 SlowBuffer.prototype.write = original.SlowBufferWrite;
188 Buffer.isEncoding = original.BufferIsEncoding;
189 Buffer.byteLength = original.BufferByteLength;
190 Buffer.prototype.toString = original.BufferToString;
191 Buffer.prototype.write = original.BufferWrite;
193 if (iconv.supportsStreams) {
194 var Readable = require('stream').Readable;
196 Readable.prototype.setEncoding = original.ReadableSetEncoding;
197 delete Readable.prototype.collect;
200 original = undefined;