2 // == Extend Node primitives to use iconv-lite =================================
4 module.exports = function (iconv) {
5 var original = undefined; // Place to keep original methods.
7 iconv.extendNodeEncodings = function extendNodeEncodings() {
11 var nodeNativeEncodings = {
12 'hex': true, 'utf8': true, 'utf-8': true, 'ascii': true, 'binary': true,
13 'base64': true, 'ucs2': true, 'ucs-2': true, 'utf16le': true, 'utf-16le': true,
16 Buffer.isNativeEncoding = function(enc) {
17 return nodeNativeEncodings[enc && enc.toLowerCase()];
20 // -- SlowBuffer -----------------------------------------------------------
21 var SlowBuffer = require('buffer').SlowBuffer;
23 original.SlowBufferToString = SlowBuffer.prototype.toString;
24 SlowBuffer.prototype.toString = function(encoding, start, end) {
25 encoding = String(encoding || 'utf8').toLowerCase();
27 if (typeof end !== 'number') end = this.length;
29 // Fastpath empty strings
33 // Use native conversion when possible
34 if (Buffer.isNativeEncoding(encoding))
35 return original.SlowBufferToString.call(this, encoding, start, end);
37 // Otherwise, use our decoding method.
38 if (typeof start == 'undefined') start = 0;
39 if (typeof end == 'undefined') end = this.length;
40 return iconv.decode(this.slice(start, end), encoding);
43 original.SlowBufferWrite = SlowBuffer.prototype.write;
44 SlowBuffer.prototype.write = function(string, offset, length, encoding) {
45 // Support both (string, offset, length, encoding)
46 // and the legacy (string, encoding, offset, length)
47 if (isFinite(offset)) {
48 if (!isFinite(length)) {
59 offset = +offset || 0;
60 var remaining = this.length - offset;
65 if (length > remaining) {
69 encoding = String(encoding || 'utf8').toLowerCase();
71 // Use native conversion when possible
72 if (Buffer.isNativeEncoding(encoding))
73 return original.SlowBufferWrite.call(this, string, offset, length, encoding);
75 if (string.length > 0 && (length < 0 || offset < 0))
76 throw new RangeError('attempt to write beyond buffer bounds');
78 // Otherwise, use our encoding method.
79 var buf = iconv.encode(string, encoding);
80 if (buf.length < length) length = buf.length;
81 buf.copy(this, offset, 0, length);
85 // -- Buffer ---------------------------------------------------------------
87 original.BufferIsEncoding = Buffer.isEncoding;
88 Buffer.isEncoding = function(encoding) {
89 return Buffer.isNativeEncoding(encoding) || iconv.encodingExists(encoding);
92 original.BufferByteLength = Buffer.byteLength;
93 Buffer.byteLength = SlowBuffer.byteLength = function(str, encoding) {
94 encoding = String(encoding || 'utf8').toLowerCase();
96 // Use native conversion when possible
97 if (Buffer.isNativeEncoding(encoding))
98 return original.BufferByteLength.call(this, str, encoding);
100 // Slow, I know, but we don't have a better way yet.
101 return iconv.encode(str, encoding).length;
104 original.BufferToString = Buffer.prototype.toString;
105 Buffer.prototype.toString = function(encoding, start, end) {
106 encoding = String(encoding || 'utf8').toLowerCase();
108 // Use native conversion when possible
109 if (Buffer.isNativeEncoding(encoding))
110 return original.BufferToString.call(this, encoding, start, end);
112 // Otherwise, use our decoding method.
113 if (typeof start == 'undefined') start = 0;
114 if (typeof end == 'undefined') end = this.length;
115 return iconv.decode(this.slice(start, end), encoding);
118 original.BufferWrite = Buffer.prototype.write;
119 Buffer.prototype.write = function(string, offset, length, encoding) {
120 var _offset = offset, _length = length, _encoding = encoding;
121 // Support both (string, offset, length, encoding)
122 // and the legacy (string, encoding, offset, length)
123 if (isFinite(offset)) {
124 if (!isFinite(length)) {
135 encoding = String(encoding || 'utf8').toLowerCase();
137 // Use native conversion when possible
138 if (Buffer.isNativeEncoding(encoding))
139 return original.BufferWrite.call(this, string, _offset, _length, _encoding);
141 offset = +offset || 0;
142 var remaining = this.length - offset;
147 if (length > remaining) {
152 if (string.length > 0 && (length < 0 || offset < 0))
153 throw new RangeError('attempt to write beyond buffer bounds');
155 // Otherwise, use our encoding method.
156 var buf = iconv.encode(string, encoding);
157 if (buf.length < length) length = buf.length;
158 buf.copy(this, offset, 0, length);
161 // TODO: Set _charsWritten.
165 // -- Readable -------------------------------------------------------------
166 if (iconv.supportsStreams) {
167 var Readable = require('stream').Readable;
169 original.ReadableSetEncoding = Readable.prototype.setEncoding;
170 Readable.prototype.setEncoding = function setEncoding(enc, options) {
171 // Try to use original function when possible.
172 if (Buffer.isNativeEncoding(enc))
173 return original.ReadableSetEncoding.call(this, enc);
175 // Try to use our own decoder, it has the same interface.
176 this._readableState.decoder = iconv.getCodec(enc).decoder(options);
177 this._readableState.encoding = enc;
180 Readable.prototype.collect = iconv._collect;
184 // Remove iconv-lite Node primitive extensions.
185 iconv.undoExtendNodeEncodings = function undoExtendNodeEncodings() {
187 throw new Error("require('iconv-lite').undoExtendNodeEncodings(): Nothing to undo; extendNodeEncodings() is not called.")
189 delete Buffer.isNativeEncoding;
191 var SlowBuffer = require('buffer').SlowBuffer;
193 SlowBuffer.prototype.toString = original.SlowBufferToString;
194 SlowBuffer.prototype.write = original.SlowBufferWrite;
196 Buffer.isEncoding = original.BufferIsEncoding;
197 Buffer.byteLength = original.BufferByteLength;
198 Buffer.prototype.toString = original.BufferToString;
199 Buffer.prototype.write = original.BufferWrite;
201 if (iconv.supportsStreams) {
202 var Readable = require('stream').Readable;
204 Readable.prototype.setEncoding = original.ReadableSetEncoding;
205 delete Readable.prototype.collect;
208 original = undefined;