second
[josuexyz/.git] / node_modules / iconv-lite / lib / extend-node.js
1 "use strict";
2 var Buffer = require("buffer").Buffer;
3 // Note: not polyfilled with safer-buffer on a purpose, as overrides Buffer
4
5 // == Extend Node primitives to use iconv-lite =================================
6
7 module.exports = function (iconv) {
8     var original = undefined; // Place to keep original methods.
9
10     // Node authors rewrote Buffer internals to make it compatible with
11     // Uint8Array and we cannot patch key functions since then.
12     // Note: this does use older Buffer API on a purpose
13     iconv.supportsNodeEncodingsExtension = !(Buffer.from || new Buffer(0) instanceof Uint8Array);
14
15     iconv.extendNodeEncodings = function extendNodeEncodings() {
16         if (original) return;
17         original = {};
18
19         if (!iconv.supportsNodeEncodingsExtension) {
20             console.error("ACTION NEEDED: require('iconv-lite').extendNodeEncodings() is not supported in your version of Node");
21             console.error("See more info at https://github.com/ashtuchkin/iconv-lite/wiki/Node-v4-compatibility");
22             return;
23         }
24
25         var nodeNativeEncodings = {
26             'hex': true, 'utf8': true, 'utf-8': true, 'ascii': true, 'binary': true, 
27             'base64': true, 'ucs2': true, 'ucs-2': true, 'utf16le': true, 'utf-16le': true,
28         };
29
30         Buffer.isNativeEncoding = function(enc) {
31             return enc && nodeNativeEncodings[enc.toLowerCase()];
32         }
33
34         // -- SlowBuffer -----------------------------------------------------------
35         var SlowBuffer = require('buffer').SlowBuffer;
36
37         original.SlowBufferToString = SlowBuffer.prototype.toString;
38         SlowBuffer.prototype.toString = function(encoding, start, end) {
39             encoding = String(encoding || 'utf8').toLowerCase();
40
41             // Use native conversion when possible
42             if (Buffer.isNativeEncoding(encoding))
43                 return original.SlowBufferToString.call(this, encoding, start, end);
44
45             // Otherwise, use our decoding method.
46             if (typeof start == 'undefined') start = 0;
47             if (typeof end == 'undefined') end = this.length;
48             return iconv.decode(this.slice(start, end), encoding);
49         }
50
51         original.SlowBufferWrite = SlowBuffer.prototype.write;
52         SlowBuffer.prototype.write = function(string, offset, length, encoding) {
53             // Support both (string, offset, length, encoding)
54             // and the legacy (string, encoding, offset, length)
55             if (isFinite(offset)) {
56                 if (!isFinite(length)) {
57                     encoding = length;
58                     length = undefined;
59                 }
60             } else {  // legacy
61                 var swap = encoding;
62                 encoding = offset;
63                 offset = length;
64                 length = swap;
65             }
66
67             offset = +offset || 0;
68             var remaining = this.length - offset;
69             if (!length) {
70                 length = remaining;
71             } else {
72                 length = +length;
73                 if (length > remaining) {
74                     length = remaining;
75                 }
76             }
77             encoding = String(encoding || 'utf8').toLowerCase();
78
79             // Use native conversion when possible
80             if (Buffer.isNativeEncoding(encoding))
81                 return original.SlowBufferWrite.call(this, string, offset, length, encoding);
82
83             if (string.length > 0 && (length < 0 || offset < 0))
84                 throw new RangeError('attempt to write beyond buffer bounds');
85
86             // Otherwise, use our encoding method.
87             var buf = iconv.encode(string, encoding);
88             if (buf.length < length) length = buf.length;
89             buf.copy(this, offset, 0, length);
90             return length;
91         }
92
93         // -- Buffer ---------------------------------------------------------------
94
95         original.BufferIsEncoding = Buffer.isEncoding;
96         Buffer.isEncoding = function(encoding) {
97             return Buffer.isNativeEncoding(encoding) || iconv.encodingExists(encoding);
98         }
99
100         original.BufferByteLength = Buffer.byteLength;
101         Buffer.byteLength = SlowBuffer.byteLength = function(str, encoding) {
102             encoding = String(encoding || 'utf8').toLowerCase();
103
104             // Use native conversion when possible
105             if (Buffer.isNativeEncoding(encoding))
106                 return original.BufferByteLength.call(this, str, encoding);
107
108             // Slow, I know, but we don't have a better way yet.
109             return iconv.encode(str, encoding).length;
110         }
111
112         original.BufferToString = Buffer.prototype.toString;
113         Buffer.prototype.toString = function(encoding, start, end) {
114             encoding = String(encoding || 'utf8').toLowerCase();
115
116             // Use native conversion when possible
117             if (Buffer.isNativeEncoding(encoding))
118                 return original.BufferToString.call(this, encoding, start, end);
119
120             // Otherwise, use our decoding method.
121             if (typeof start == 'undefined') start = 0;
122             if (typeof end == 'undefined') end = this.length;
123             return iconv.decode(this.slice(start, end), encoding);
124         }
125
126         original.BufferWrite = Buffer.prototype.write;
127         Buffer.prototype.write = function(string, offset, length, encoding) {
128             var _offset = offset, _length = length, _encoding = encoding;
129             // Support both (string, offset, length, encoding)
130             // and the legacy (string, encoding, offset, length)
131             if (isFinite(offset)) {
132                 if (!isFinite(length)) {
133                     encoding = length;
134                     length = undefined;
135                 }
136             } else {  // legacy
137                 var swap = encoding;
138                 encoding = offset;
139                 offset = length;
140                 length = swap;
141             }
142
143             encoding = String(encoding || 'utf8').toLowerCase();
144
145             // Use native conversion when possible
146             if (Buffer.isNativeEncoding(encoding))
147                 return original.BufferWrite.call(this, string, _offset, _length, _encoding);
148
149             offset = +offset || 0;
150             var remaining = this.length - offset;
151             if (!length) {
152                 length = remaining;
153             } else {
154                 length = +length;
155                 if (length > remaining) {
156                     length = remaining;
157                 }
158             }
159
160             if (string.length > 0 && (length < 0 || offset < 0))
161                 throw new RangeError('attempt to write beyond buffer bounds');
162
163             // Otherwise, use our encoding method.
164             var buf = iconv.encode(string, encoding);
165             if (buf.length < length) length = buf.length;
166             buf.copy(this, offset, 0, length);
167             return length;
168
169             // TODO: Set _charsWritten.
170         }
171
172
173         // -- Readable -------------------------------------------------------------
174         if (iconv.supportsStreams) {
175             var Readable = require('stream').Readable;
176
177             original.ReadableSetEncoding = Readable.prototype.setEncoding;
178             Readable.prototype.setEncoding = function setEncoding(enc, options) {
179                 // Use our own decoder, it has the same interface.
180                 // We cannot use original function as it doesn't handle BOM-s.
181                 this._readableState.decoder = iconv.getDecoder(enc, options);
182                 this._readableState.encoding = enc;
183             }
184
185             Readable.prototype.collect = iconv._collect;
186         }
187     }
188
189     // Remove iconv-lite Node primitive extensions.
190     iconv.undoExtendNodeEncodings = function undoExtendNodeEncodings() {
191         if (!iconv.supportsNodeEncodingsExtension)
192             return;
193         if (!original)
194             throw new Error("require('iconv-lite').undoExtendNodeEncodings(): Nothing to undo; extendNodeEncodings() is not called.")
195
196         delete Buffer.isNativeEncoding;
197
198         var SlowBuffer = require('buffer').SlowBuffer;
199
200         SlowBuffer.prototype.toString = original.SlowBufferToString;
201         SlowBuffer.prototype.write = original.SlowBufferWrite;
202
203         Buffer.isEncoding = original.BufferIsEncoding;
204         Buffer.byteLength = original.BufferByteLength;
205         Buffer.prototype.toString = original.BufferToString;
206         Buffer.prototype.write = original.BufferWrite;
207
208         if (iconv.supportsStreams) {
209             var Readable = require('stream').Readable;
210
211             Readable.prototype.setEncoding = original.ReadableSetEncoding;
212             delete Readable.prototype.collect;
213         }
214
215         original = undefined;
216     }
217 }