@@ -24,82 +24,148 @@ function createPool() {
2424}
2525createPool ( ) ;
2626
27+ function Buffer ( arg ) {
28+ if ( ! ( this instanceof Buffer ) ) {
29+ // Avoid going through an ArgumentsAdaptorTrampoline in the common case.
30+ if ( arguments . length > 1 )
31+ return new Buffer ( arg , arguments [ 1 ] ) ;
2732
28- function Buffer ( subject , encoding ) {
29- if ( ! ( this instanceof Buffer ) )
30- return new Buffer ( subject , encoding ) ;
31-
32- if ( typeof subject === 'number' ) {
33- this . length = + subject ;
34-
35- } else if ( typeof subject === 'string' ) {
36- if ( typeof encoding !== 'string' || encoding . length === 0 )
37- encoding = 'utf8' ;
38- this . length = Buffer . byteLength ( subject , encoding ) ;
33+ return new Buffer ( arg ) ;
34+ }
3935
40- // Handle Arrays, Buffers, Uint8Arrays or JSON.
41- } else if ( subject !== null && typeof subject === 'object' ) {
42- if ( subject . type === 'Buffer' && Array . isArray ( subject . data ) )
43- subject = subject . data ;
44- this . length = + subject . length ;
36+ this . length = 0 ;
37+ this . parent = undefined ;
4538
46- } else {
47- throw new TypeError ( 'must start with number, buffer, array or string' ) ;
39+ // Common case.
40+ if ( typeof ( arg ) === 'number' ) {
41+ fromNumber ( this , arg ) ;
42+ return ;
4843 }
4944
50- if ( this . length > kMaxLength ) {
51- throw new RangeError ( 'Attempt to allocate Buffer larger than maximum ' +
52- 'size: 0x' + kMaxLength . toString ( 16 ) + ' bytes' ) ;
45+ // Slightly less common case.
46+ if ( typeof ( arg ) === 'string' ) {
47+ fromString ( this , arg , arguments . length > 1 ? arguments [ 1 ] : 'utf8' ) ;
48+ return ;
5349 }
5450
55- if ( this . length < 0 )
56- this . length = 0 ;
57- else
58- this . length >>>= 0 ; // Coerce to uint32.
51+ // Unusual.
52+ fromObject ( this , arg ) ;
53+ }
5954
60- this . parent = undefined ;
61- if ( this . length <= ( Buffer . poolSize >>> 1 ) && this . length > 0 ) {
62- if ( this . length > poolSize - poolOffset )
63- createPool ( ) ;
64- this . parent = sliceOnto ( allocPool ,
65- this ,
66- poolOffset ,
67- poolOffset + this . length ) ;
68- poolOffset += this . length ;
69- } else {
70- alloc ( this , this . length ) ;
71- }
55+ function fromNumber ( that , length ) {
56+ allocate ( that , length < 0 ? 0 : checked ( length ) | 0 ) ;
57+ }
7258
73- if ( typeof subject === 'number' ) {
74- return ;
59+ function fromString ( that , string , encoding ) {
60+ if ( typeof ( encoding ) !== 'string' || encoding === '' )
61+ encoding = 'utf8' ;
62+
63+ // Assumption: byteLength() return value is always < kMaxLength.
64+ var length = byteLength ( string , encoding ) | 0 ;
65+ allocate ( that , length ) ;
66+
67+ var actual = that . write ( string , encoding ) | 0 ;
68+ if ( actual !== length ) {
69+ // Fix up for truncated base64 input. Don't bother returning
70+ // the unused two or three bytes to the pool.
71+ that . length = actual ;
72+ truncate ( that , actual ) ;
7573 }
74+ }
7675
77- if ( typeof subject === 'string' ) {
78- // In the case of base64 it's possible that the size of the buffer
79- // allocated was slightly too large. In this case we need to rewrite
80- // the length to the actual length written.
81- var len = this . write ( subject , encoding ) ;
82- // Buffer was truncated after decode, realloc internal ExternalArray
83- if ( len !== this . length ) {
84- var prevLen = this . length ;
85- this . length = len ;
86- truncate ( this , this . length ) ;
87- // Only need to readjust the poolOffset if the allocation is a slice.
88- if ( this . parent != undefined )
89- poolOffset -= ( prevLen - len ) ;
90- }
76+ function fromObject ( that , object ) {
77+ if ( object instanceof Buffer )
78+ return fromBuffer ( that , object ) ;
79+
80+ if ( Array . isArray ( object ) )
81+ return fromArray ( that , object ) ;
82+
83+ if ( object == null )
84+ throw new TypeError ( 'must start with number, buffer, array or string' ) ;
9185
92- } else if ( subject instanceof Buffer ) {
93- subject . copy ( this , 0 , 0 , this . length ) ;
86+ if ( object . buffer instanceof ArrayBuffer )
87+ return fromTypedArray ( that , object ) ;
88+
89+ if ( object . length )
90+ return fromArrayLike ( that , object ) ;
91+
92+ return fromJsonObject ( that , object ) ;
93+ }
94+
95+ function fromBuffer ( that , buffer ) {
96+ var length = checked ( buffer . length ) | 0 ;
97+ allocate ( that , length ) ;
98+ buffer . copy ( that , 0 , 0 , length ) ;
99+ }
100+
101+ function fromArray ( that , array ) {
102+ var length = checked ( array . length ) | 0 ;
103+ allocate ( that , length ) ;
104+ for ( var i = 0 ; i < length ; i += 1 )
105+ that [ i ] = array [ i ] & 255 ;
106+ }
94107
95- } else if ( typeof subject . length === 'number' || Array . isArray ( subject ) ) {
96- // Really crappy way to handle Uint8Arrays, but V8 doesn't give a simple
97- // way to access the data from the C++ API.
98- for ( var i = 0 ; i < this . length ; i ++ )
99- this [ i ] = subject [ i ] ;
108+ // Duplicate of fromArray() to keep fromArray() monomorphic.
109+ function fromTypedArray ( that , array ) {
110+ var length = checked ( array . length ) | 0 ;
111+ allocate ( that , length ) ;
112+ // Truncating the elements is probably not what people expect from typed
113+ // arrays with BYTES_PER_ELEMENT > 1 but it's compatible with the behavior
114+ // of the old Buffer constructor.
115+ for ( var i = 0 ; i < length ; i += 1 )
116+ that [ i ] = array [ i ] & 255 ;
117+ }
118+
119+ function fromArrayLike ( that , array ) {
120+ var length = checked ( array . length ) | 0 ;
121+ allocate ( that , length ) ;
122+ for ( var i = 0 ; i < length ; i += 1 )
123+ that [ i ] = array [ i ] & 255 ;
124+ }
125+
126+ // Deserialize { type: 'Buffer', data: [1,2,3,...] } into a Buffer object.
127+ // Returns a zero-length buffer for inputs that don't conform to the spec.
128+ function fromJsonObject ( that , object ) {
129+ var array ;
130+ var length = 0 ;
131+
132+ if ( object . type === 'Buffer' && Array . isArray ( object . data ) ) {
133+ array = object . data ;
134+ length = checked ( array . length ) | 0 ;
100135 }
136+ allocate ( that , length ) ;
137+
138+ for ( var i = 0 ; i < length ; i += 1 )
139+ that [ i ] = array [ i ] & 255 ;
140+ }
141+
142+ function allocate ( that , length ) {
143+ var fromPool = length !== 0 && length <= Buffer . poolSize >>> 1 ;
144+ that . parent = fromPool ? palloc ( that , length ) : alloc ( that , length ) ;
145+ that . length = length ;
101146}
102147
148+ function palloc ( that , length ) {
149+ if ( length > poolSize - poolOffset )
150+ createPool ( ) ;
151+
152+ var start = poolOffset ;
153+ var end = start + length ;
154+ var buf = sliceOnto ( allocPool , that , start , end ) ;
155+ poolOffset = end ;
156+
157+ return buf ;
158+ }
159+
160+ function checked ( length ) {
161+ // Note: cannot use `length < kMaxLength` here because that fails when
162+ // length is NaN (which is otherwise coerced to zero.)
163+ if ( length >= kMaxLength ) {
164+ throw new RangeError ( 'Attempt to allocate Buffer larger than maximum ' +
165+ 'size: 0x' + kMaxLength . toString ( 16 ) + ' bytes' ) ;
166+ }
167+ return length >>> 0 ;
168+ }
103169
104170function SlowBuffer ( length ) {
105171 length = length >>> 0 ;
@@ -197,30 +263,30 @@ Buffer.concat = function(list, length) {
197263} ;
198264
199265
200- Buffer . byteLength = function ( str , enc ) {
201- var ret ;
202- str = str + '' ;
203- switch ( enc ) {
266+ function byteLength ( string , encoding ) {
267+ if ( typeof ( string ) !== 'string' )
268+ string = String ( string ) ;
269+
270+ switch ( encoding ) {
204271 case 'ascii' :
205272 case 'binary' :
206273 case 'raw' :
207- ret = str . length ;
208- break ;
274+ return string . length ;
275+
209276 case 'ucs2' :
210277 case 'ucs-2' :
211278 case 'utf16le' :
212279 case 'utf-16le' :
213- ret = str . length * 2 ;
214- break ;
280+ return string . length * 2 ;
281+
215282 case 'hex' :
216- ret = str . length >>> 1 ;
217- break ;
218- default :
219- ret = binding . byteLength ( str , enc ) ;
283+ return string . length >>> 1 ;
220284 }
221- return ret ;
222- } ;
223285
286+ return binding . byteLength ( string , encoding ) ;
287+ }
288+
289+ Buffer . byteLength = byteLength ;
224290
225291// toString(encoding, start=0, end=buffer.length)
226292Buffer . prototype . toString = function ( encoding , start , end ) {
0 commit comments