bl 2.1.0 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.jshintrc CHANGED
@@ -22,7 +22,7 @@
22
22
  , "boss": true
23
23
  , "debug": true
24
24
  , "eqnull": true
25
- , "esnext": true
25
+ , "esnext": false
26
26
  , "evil": true
27
27
  , "expr": true
28
28
  , "funcscope": false
@@ -56,4 +56,5 @@
56
56
  , "nomen": false
57
57
  , "onevar": false
58
58
  , "passfail": false
59
+ , "esversion": 3
59
60
  }
package/README.md CHANGED
@@ -15,11 +15,11 @@ The original buffers are kept intact and copies are only done as necessary. Any
15
15
  const BufferList = require('bl')
16
16
 
17
17
  var bl = new BufferList()
18
- bl.append(new Buffer('abcd'))
19
- bl.append(new Buffer('efg'))
18
+ bl.append(Buffer.from('abcd'))
19
+ bl.append(Buffer.from('efg'))
20
20
  bl.append('hi') // bl will also accept & convert Strings
21
- bl.append(new Buffer('j'))
22
- bl.append(new Buffer([ 0x3, 0x4 ]))
21
+ bl.append(Buffer.from('j'))
22
+ bl.append(Buffer.from([ 0x3, 0x4 ]))
23
23
 
24
24
  console.log(bl.length) // 12
25
25
 
@@ -29,6 +29,9 @@ console.log(bl.slice(3, 6).toString('ascii')) // 'def'
29
29
  console.log(bl.slice(3, 8).toString('ascii')) // 'defgh'
30
30
  console.log(bl.slice(5, 10).toString('ascii')) // 'fghij'
31
31
 
32
+ console.log(bl.indexOf('def')) // 3
33
+ console.log(bl.indexOf('asdf')) // -1
34
+
32
35
  // or just use toString!
33
36
  console.log(bl.toString()) // 'abcdefghij\u0003\u0004'
34
37
  console.log(bl.toString('ascii', 3, 8)) // 'defgh'
@@ -72,10 +75,10 @@ const BufferList = require('bl')
72
75
  , fs = require('fs')
73
76
 
74
77
  var bl = new BufferList()
75
- bl.append(new Buffer('abcd'))
76
- bl.append(new Buffer('efg'))
77
- bl.append(new Buffer('hi'))
78
- bl.append(new Buffer('j'))
78
+ bl.append(Buffer.from('abcd'))
79
+ bl.append(Buffer.from('efg'))
80
+ bl.append(Buffer.from('hi'))
81
+ bl.append(Buffer.from('j'))
79
82
 
80
83
  bl.pipe(fs.createWriteStream('gibberish.txt'))
81
84
  ```
@@ -86,6 +89,7 @@ bl.pipe(fs.createWriteStream('gibberish.txt'))
86
89
  * <a href="#length"><code>bl.<b>length</b></code></a>
87
90
  * <a href="#append"><code>bl.<b>append(buffer)</b></code></a>
88
91
  * <a href="#get"><code>bl.<b>get(index)</b></code></a>
92
+ * <a href="#indexOf"><code>bl.<b>indexOf(value[, byteOffset][, encoding])</b></code></a>
89
93
  * <a href="#slice"><code>bl.<b>slice([ start[, end ] ])</b></code></a>
90
94
  * <a href="#shallowSlice"><code>bl.<b>shallowSlice([ start[, end ] ])</b></code></a>
91
95
  * <a href="#copy"><code>bl.<b>copy(dest, [ destStart, [ srcStart [, srcEnd ] ] ])</b></code></a>
@@ -129,6 +133,12 @@ Get the length of the list in bytes. This is the sum of the lengths of all of th
129
133
  ### bl.get(index)
130
134
  `get()` will return the byte at the specified index.
131
135
 
136
+ --------------------------------------------------------
137
+ <a name="indexOf"></a>
138
+ ### bl.indexOf(value[, byteOffset][, encoding])
139
+ `get()` will return the byte at the specified index.
140
+ `indexOf()` method returns the first index at which a given element can be found in the BufferList, or -1 if it is not present.
141
+
132
142
  --------------------------------------------------------
133
143
  <a name="slice"></a>
134
144
  ### bl.slice([ start, [ end ] ])
package/bl.js CHANGED
@@ -3,8 +3,6 @@ var DuplexStream = require('readable-stream').Duplex
3
3
  , util = require('util')
4
4
  , Buffer = require('safe-buffer').Buffer
5
5
 
6
- var tempBuffer = Buffer.alloc(1)
7
-
8
6
  function BufferList (callback) {
9
7
  if (!(this instanceof BufferList))
10
8
  return new BufferList(callback)
@@ -52,9 +50,9 @@ BufferList.prototype._offset = function _offset (offset) {
52
50
  }
53
51
 
54
52
  BufferList.prototype._reverseOffset = function (blOffset) {
55
- const bufferId = blOffset[0]
56
- let offset = blOffset[1]
57
- for (let i = 0; i < bufferId; i++) {
53
+ var bufferId = blOffset[0]
54
+ var offset = blOffset[1]
55
+ for (var i = 0; i < bufferId; i++) {
58
56
  offset += this._bufs[i].length
59
57
  }
60
58
  return offset
@@ -120,8 +118,11 @@ BufferList.prototype.end = function end (chunk) {
120
118
 
121
119
 
122
120
  BufferList.prototype.get = function get (index) {
123
- this.copy(tempBuffer, 0, index, index + 1)
124
- return tempBuffer[0]
121
+ if (index > this.length || index < 0) {
122
+ return undefined
123
+ }
124
+ var offset = this._offset(index)
125
+ return this._bufs[offset[0]][offset[1]]
125
126
  }
126
127
 
127
128
 
@@ -185,30 +186,37 @@ BufferList.prototype.copy = function copy (dst, dstStart, srcStart, srcEnd) {
185
186
 
186
187
  if (bytes > l) {
187
188
  this._bufs[i].copy(dst, bufoff, start)
189
+ bufoff += l
188
190
  } else {
189
191
  this._bufs[i].copy(dst, bufoff, start, start + bytes)
192
+ bufoff += l
190
193
  break
191
194
  }
192
195
 
193
- bufoff += l
194
196
  bytes -= l
195
197
 
196
198
  if (start)
197
199
  start = 0
198
200
  }
199
201
 
202
+ // safeguard so that we don't return uninitialized memory
203
+ if (dst.length > bufoff) return dst.slice(0, bufoff)
204
+
200
205
  return dst
201
206
  }
202
207
 
203
208
  BufferList.prototype.shallowSlice = function shallowSlice (start, end) {
204
209
  start = start || 0
205
- end = end || this.length
210
+ end = typeof end !== 'number' ? this.length : end
206
211
 
207
212
  if (start < 0)
208
213
  start += this.length
209
214
  if (end < 0)
210
215
  end += this.length
211
216
 
217
+ if (start === end) {
218
+ return new BufferList()
219
+ }
212
220
  var startOffset = this._offset(start)
213
221
  , endOffset = this._offset(end)
214
222
  , buffers = this._bufs.slice(startOffset[0], endOffset[0] + 1)
@@ -229,6 +237,11 @@ BufferList.prototype.toString = function toString (encoding, start, end) {
229
237
  }
230
238
 
231
239
  BufferList.prototype.consume = function consume (bytes) {
240
+ // first, normalize the argument, in accordance with how Buffer does it
241
+ bytes = Math.trunc(bytes)
242
+ // do nothing if not a positive number
243
+ if (Number.isNaN(bytes) || bytes <= 0) return this
244
+
232
245
  while (this._bufs.length) {
233
246
  if (bytes >= this._bufs[0].length) {
234
247
  bytes -= this._bufs[0].length
@@ -261,6 +274,7 @@ BufferList.prototype.destroy = function destroy () {
261
274
  this.push(null)
262
275
  }
263
276
 
277
+
264
278
  BufferList.prototype.indexOf = function (search, offset, encoding) {
265
279
  if (encoding === undefined && typeof offset === 'string') {
266
280
  encoding = offset
@@ -272,10 +286,11 @@ BufferList.prototype.indexOf = function (search, offset, encoding) {
272
286
  search = Buffer.from([search])
273
287
  } else if (typeof search === 'string') {
274
288
  search = Buffer.from(search, encoding)
275
- } else if (!search instanceof BufferList && !Buffer.isBuffer(search)) {
289
+ } else if (search instanceof BufferList) {
290
+ search = search.slice()
291
+ } else if (!Buffer.isBuffer(search)) {
276
292
  search = Buffer.from(search)
277
293
  }
278
- search = new BufferList(search)
279
294
 
280
295
  offset = Number(offset || 0)
281
296
  if (isNaN(offset)) {
@@ -294,49 +309,44 @@ BufferList.prototype.indexOf = function (search, offset, encoding) {
294
309
  return offset > this.length ? this.length : offset
295
310
  }
296
311
 
297
- // Use the native buffer indexOf
298
- if (search.length === 1) {
299
- const searchBuffer = search.slice()
300
- const blOffset = this._offset(offset)
301
- let blIndex = blOffset[0]
302
- let buffOffset = blOffset[1]
303
-
304
- for (blIndex; blIndex < this._bufs.length; blIndex++) {
305
- let position = this._bufs[blIndex].indexOf(searchBuffer, buffOffset)
306
- if (position !== -1) {
307
- return this._reverseOffset([blIndex, position])
312
+ var blOffset = this._offset(offset)
313
+ var blIndex = blOffset[0] // index of which internal buffer we're working on
314
+ var buffOffset = blOffset[1] // offset of the internal buffer we're working on
315
+
316
+ // scan over each buffer
317
+ for (blIndex; blIndex < this._bufs.length; blIndex++) {
318
+ var buff = this._bufs[blIndex]
319
+ while(buffOffset < buff.length) {
320
+ var availableWindow = buff.length - buffOffset
321
+ if (availableWindow >= search.length) {
322
+ var nativeSearchResult = buff.indexOf(search, buffOffset)
323
+ if (nativeSearchResult !== -1) {
324
+ return this._reverseOffset([blIndex, nativeSearchResult])
325
+ }
326
+ buffOffset = buff.length - search.length + 1 // end of native search window
327
+ } else {
328
+ var revOffset = this._reverseOffset([blIndex, buffOffset])
329
+ if (this._match(revOffset, search)) {
330
+ return revOffset
331
+ }
332
+ buffOffset++
308
333
  }
309
- buffOffset = 0
310
334
  }
311
- return -1
335
+ buffOffset = 0
312
336
  }
337
+ return -1
338
+ }
313
339
 
314
-
315
- let searchOffset = 0
316
- let searchPosition = -1
317
-
318
- for (let blSearchOffset = offset; blSearchOffset < this.length ; ++blSearchOffset) {
319
- if(this.get(blSearchOffset) != search.get(searchOffset)){
320
- searchPosition = -1
321
- blSearchOffset -= searchOffset-1
322
- searchOffset = 0
323
- }
324
-
325
- if(this.get(blSearchOffset) == search.get(searchOffset)) {
326
- if(searchPosition == -1) {
327
- searchPosition = blSearchOffset
328
- }
329
- ++searchOffset
330
- if(searchOffset == search.length) {
331
- break
332
- }
333
- }
340
+ BufferList.prototype._match = function(offset, search) {
341
+ if (this.length - offset < search.length) {
342
+ return false
334
343
  }
335
-
336
- if (searchPosition > -1 && this.length - searchPosition < search.length) {
337
- return -1
344
+ for (var searchOffset = 0; searchOffset < search.length ; searchOffset++) {
345
+ if(this.get(offset + searchOffset) !== search[searchOffset]){
346
+ return false
347
+ }
338
348
  }
339
- return searchPosition
349
+ return true
340
350
  }
341
351
 
342
352
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bl",
3
- "version": "2.1.0",
3
+ "version": "2.2.1",
4
4
  "description": "Buffer List: collect buffers and access with a standard readable Buffer interface, streamable too!",
5
5
  "main": "bl.js",
6
6
  "scripts": {
@@ -0,0 +1,463 @@
1
+ 'use strict'
2
+
3
+ var tape = require('tape')
4
+ , BufferList = require('../')
5
+ , Buffer = require('safe-buffer').Buffer
6
+
7
+ tape('indexOf single byte needle', t => {
8
+ const bl = new BufferList(['abcdefg', 'abcdefg', '12345'])
9
+ t.equal(bl.indexOf('e'), 4)
10
+ t.equal(bl.indexOf('e', 5), 11)
11
+ t.equal(bl.indexOf('e', 12), -1)
12
+ t.equal(bl.indexOf('5'), 18)
13
+ t.end()
14
+ })
15
+
16
+ tape('indexOf multiple byte needle', t => {
17
+ const bl = new BufferList(['abcdefg', 'abcdefg'])
18
+ t.equal(bl.indexOf('ef'), 4)
19
+ t.equal(bl.indexOf('ef', 5), 11)
20
+ t.end()
21
+ })
22
+
23
+ tape('indexOf multiple byte needles across buffer boundaries', t => {
24
+ const bl = new BufferList(['abcdefg', 'abcdefg'])
25
+ t.equal(bl.indexOf('fgabc'), 5)
26
+ t.end()
27
+ })
28
+
29
+ tape('indexOf takes a buffer list search', t => {
30
+ const bl = new BufferList(['abcdefg', 'abcdefg'])
31
+ const search = new BufferList('fgabc')
32
+ t.equal(bl.indexOf(search), 5)
33
+ t.end()
34
+ })
35
+
36
+ tape('indexOf a zero byte needle', t => {
37
+ const b = new BufferList('abcdef')
38
+ const buf_empty = Buffer.from('')
39
+ t.equal(b.indexOf(''), 0)
40
+ t.equal(b.indexOf('', 1), 1)
41
+ t.equal(b.indexOf('', b.length + 1), b.length)
42
+ t.equal(b.indexOf('', Infinity), b.length)
43
+ t.equal(b.indexOf(buf_empty), 0)
44
+ t.equal(b.indexOf(buf_empty, 1), 1)
45
+ t.equal(b.indexOf(buf_empty, b.length + 1), b.length)
46
+ t.equal(b.indexOf(buf_empty, Infinity), b.length)
47
+ t.end()
48
+ })
49
+
50
+ tape('indexOf buffers smaller and larger than the needle', t => {
51
+ const bl = new BufferList(['abcdefg', 'a', 'bcdefg', 'a', 'bcfgab'])
52
+ t.equal(bl.indexOf('fgabc'), 5)
53
+ t.equal(bl.indexOf('fgabc', 6), 12)
54
+ t.equal(bl.indexOf('fgabc', 13), -1)
55
+ t.end()
56
+ })
57
+
58
+ // only present in node 6+
59
+ ;(process.version.substr(1).split('.')[0] >= 6) && tape('indexOf latin1 and binary encoding', t => {
60
+ const b = new BufferList('abcdef')
61
+
62
+ // test latin1 encoding
63
+ t.equal(
64
+ new BufferList(Buffer.from(b.toString('latin1'), 'latin1'))
65
+ .indexOf('d', 0, 'latin1'),
66
+ 3
67
+ )
68
+ t.equal(
69
+ new BufferList(Buffer.from(b.toString('latin1'), 'latin1'))
70
+ .indexOf(Buffer.from('d', 'latin1'), 0, 'latin1'),
71
+ 3
72
+ )
73
+ t.equal(
74
+ new BufferList(Buffer.from('aa\u00e8aa', 'latin1'))
75
+ .indexOf('\u00e8', 'latin1'),
76
+ 2
77
+ )
78
+ t.equal(
79
+ new BufferList(Buffer.from('\u00e8', 'latin1'))
80
+ .indexOf('\u00e8', 'latin1'),
81
+ 0
82
+ )
83
+ t.equal(
84
+ new BufferList(Buffer.from('\u00e8', 'latin1'))
85
+ .indexOf(Buffer.from('\u00e8', 'latin1'), 'latin1'),
86
+ 0
87
+ )
88
+
89
+ // test binary encoding
90
+ t.equal(
91
+ new BufferList(Buffer.from(b.toString('binary'), 'binary'))
92
+ .indexOf('d', 0, 'binary'),
93
+ 3
94
+ )
95
+ t.equal(
96
+ new BufferList(Buffer.from(b.toString('binary'), 'binary'))
97
+ .indexOf(Buffer.from('d', 'binary'), 0, 'binary'),
98
+ 3
99
+ )
100
+ t.equal(
101
+ new BufferList(Buffer.from('aa\u00e8aa', 'binary'))
102
+ .indexOf('\u00e8', 'binary'),
103
+ 2
104
+ )
105
+ t.equal(
106
+ new BufferList(Buffer.from('\u00e8', 'binary'))
107
+ .indexOf('\u00e8', 'binary'),
108
+ 0
109
+ )
110
+ t.equal(
111
+ new BufferList(Buffer.from('\u00e8', 'binary'))
112
+ .indexOf(Buffer.from('\u00e8', 'binary'), 'binary'),
113
+ 0
114
+ )
115
+ t.end()
116
+ })
117
+
118
+ tape('indexOf the entire nodejs10 buffer test suite', t => {
119
+ const b = new BufferList('abcdef')
120
+ const buf_a = Buffer.from('a')
121
+ const buf_bc = Buffer.from('bc')
122
+ const buf_f = Buffer.from('f')
123
+ const buf_z = Buffer.from('z')
124
+
125
+ const stringComparison = 'abcdef'
126
+
127
+ t.equal(b.indexOf('a'), 0)
128
+ t.equal(b.indexOf('a', 1), -1)
129
+ t.equal(b.indexOf('a', -1), -1)
130
+ t.equal(b.indexOf('a', -4), -1)
131
+ t.equal(b.indexOf('a', -b.length), 0)
132
+ t.equal(b.indexOf('a', NaN), 0)
133
+ t.equal(b.indexOf('a', -Infinity), 0)
134
+ t.equal(b.indexOf('a', Infinity), -1)
135
+ t.equal(b.indexOf('bc'), 1)
136
+ t.equal(b.indexOf('bc', 2), -1)
137
+ t.equal(b.indexOf('bc', -1), -1)
138
+ t.equal(b.indexOf('bc', -3), -1)
139
+ t.equal(b.indexOf('bc', -5), 1)
140
+ t.equal(b.indexOf('bc', NaN), 1)
141
+ t.equal(b.indexOf('bc', -Infinity), 1)
142
+ t.equal(b.indexOf('bc', Infinity), -1)
143
+ t.equal(b.indexOf('f'), b.length - 1)
144
+ t.equal(b.indexOf('z'), -1)
145
+ // empty search tests
146
+ t.equal(b.indexOf(buf_a), 0)
147
+ t.equal(b.indexOf(buf_a, 1), -1)
148
+ t.equal(b.indexOf(buf_a, -1), -1)
149
+ t.equal(b.indexOf(buf_a, -4), -1)
150
+ t.equal(b.indexOf(buf_a, -b.length), 0)
151
+ t.equal(b.indexOf(buf_a, NaN), 0)
152
+ t.equal(b.indexOf(buf_a, -Infinity), 0)
153
+ t.equal(b.indexOf(buf_a, Infinity), -1)
154
+ t.equal(b.indexOf(buf_bc), 1)
155
+ t.equal(b.indexOf(buf_bc, 2), -1)
156
+ t.equal(b.indexOf(buf_bc, -1), -1)
157
+ t.equal(b.indexOf(buf_bc, -3), -1)
158
+ t.equal(b.indexOf(buf_bc, -5), 1)
159
+ t.equal(b.indexOf(buf_bc, NaN), 1)
160
+ t.equal(b.indexOf(buf_bc, -Infinity), 1)
161
+ t.equal(b.indexOf(buf_bc, Infinity), -1)
162
+ t.equal(b.indexOf(buf_f), b.length - 1)
163
+ t.equal(b.indexOf(buf_z), -1)
164
+ t.equal(b.indexOf(0x61), 0)
165
+ t.equal(b.indexOf(0x61, 1), -1)
166
+ t.equal(b.indexOf(0x61, -1), -1)
167
+ t.equal(b.indexOf(0x61, -4), -1)
168
+ t.equal(b.indexOf(0x61, -b.length), 0)
169
+ t.equal(b.indexOf(0x61, NaN), 0)
170
+ t.equal(b.indexOf(0x61, -Infinity), 0)
171
+ t.equal(b.indexOf(0x61, Infinity), -1)
172
+ t.equal(b.indexOf(0x0), -1)
173
+
174
+ // test offsets
175
+ t.equal(b.indexOf('d', 2), 3)
176
+ t.equal(b.indexOf('f', 5), 5)
177
+ t.equal(b.indexOf('f', -1), 5)
178
+ t.equal(b.indexOf('f', 6), -1)
179
+
180
+ t.equal(b.indexOf(Buffer.from('d'), 2), 3)
181
+ t.equal(b.indexOf(Buffer.from('f'), 5), 5)
182
+ t.equal(b.indexOf(Buffer.from('f'), -1), 5)
183
+ t.equal(b.indexOf(Buffer.from('f'), 6), -1)
184
+
185
+ t.equal(Buffer.from('ff').indexOf(Buffer.from('f'), 1, 'ucs2'), -1)
186
+
187
+ // test invalid and uppercase encoding
188
+ t.equal(b.indexOf('b', 'utf8'), 1)
189
+ t.equal(b.indexOf('b', 'UTF8'), 1)
190
+ t.equal(b.indexOf('62', 'HEX'), 1)
191
+ t.throws(() => b.indexOf('bad', 'enc'), TypeError)
192
+
193
+ // test hex encoding
194
+ t.equal(
195
+ Buffer.from(b.toString('hex'), 'hex')
196
+ .indexOf('64', 0, 'hex'),
197
+ 3
198
+ )
199
+ t.equal(
200
+ Buffer.from(b.toString('hex'), 'hex')
201
+ .indexOf(Buffer.from('64', 'hex'), 0, 'hex'),
202
+ 3
203
+ )
204
+
205
+ // test base64 encoding
206
+ t.equal(
207
+ Buffer.from(b.toString('base64'), 'base64')
208
+ .indexOf('ZA==', 0, 'base64'),
209
+ 3
210
+ )
211
+ t.equal(
212
+ Buffer.from(b.toString('base64'), 'base64')
213
+ .indexOf(Buffer.from('ZA==', 'base64'), 0, 'base64'),
214
+ 3
215
+ )
216
+
217
+ // test ascii encoding
218
+ t.equal(
219
+ Buffer.from(b.toString('ascii'), 'ascii')
220
+ .indexOf('d', 0, 'ascii'),
221
+ 3
222
+ )
223
+ t.equal(
224
+ Buffer.from(b.toString('ascii'), 'ascii')
225
+ .indexOf(Buffer.from('d', 'ascii'), 0, 'ascii'),
226
+ 3
227
+ )
228
+
229
+ // test optional offset with passed encoding
230
+ t.equal(Buffer.from('aaaa0').indexOf('30', 'hex'), 4)
231
+ t.equal(Buffer.from('aaaa00a').indexOf('3030', 'hex'), 4)
232
+
233
+ {
234
+ // test usc2 encoding
235
+ const twoByteString = Buffer.from('\u039a\u0391\u03a3\u03a3\u0395', 'ucs2')
236
+
237
+ t.equal(8, twoByteString.indexOf('\u0395', 4, 'ucs2'))
238
+ t.equal(6, twoByteString.indexOf('\u03a3', -4, 'ucs2'))
239
+ t.equal(4, twoByteString.indexOf('\u03a3', -6, 'ucs2'))
240
+ t.equal(4, twoByteString.indexOf(
241
+ Buffer.from('\u03a3', 'ucs2'), -6, 'ucs2'))
242
+ t.equal(-1, twoByteString.indexOf('\u03a3', -2, 'ucs2'))
243
+ }
244
+
245
+ const mixedByteStringUcs2 =
246
+ Buffer.from('\u039a\u0391abc\u03a3\u03a3\u0395', 'ucs2')
247
+ t.equal(6, mixedByteStringUcs2.indexOf('bc', 0, 'ucs2'))
248
+ t.equal(10, mixedByteStringUcs2.indexOf('\u03a3', 0, 'ucs2'))
249
+ t.equal(-1, mixedByteStringUcs2.indexOf('\u0396', 0, 'ucs2'))
250
+
251
+ t.equal(
252
+ 6, mixedByteStringUcs2.indexOf(Buffer.from('bc', 'ucs2'), 0, 'ucs2'))
253
+ t.equal(
254
+ 10, mixedByteStringUcs2.indexOf(Buffer.from('\u03a3', 'ucs2'), 0, 'ucs2'))
255
+ t.equal(
256
+ -1, mixedByteStringUcs2.indexOf(Buffer.from('\u0396', 'ucs2'), 0, 'ucs2'))
257
+
258
+ {
259
+ const twoByteString = Buffer.from('\u039a\u0391\u03a3\u03a3\u0395', 'ucs2')
260
+
261
+ // Test single char pattern
262
+ t.equal(0, twoByteString.indexOf('\u039a', 0, 'ucs2'))
263
+ let index = twoByteString.indexOf('\u0391', 0, 'ucs2')
264
+ t.equal(2, index, `Alpha - at index ${index}`)
265
+ index = twoByteString.indexOf('\u03a3', 0, 'ucs2')
266
+ t.equal(4, index, `First Sigma - at index ${index}`)
267
+ index = twoByteString.indexOf('\u03a3', 6, 'ucs2')
268
+ t.equal(6, index, `Second Sigma - at index ${index}`)
269
+ index = twoByteString.indexOf('\u0395', 0, 'ucs2')
270
+ t.equal(8, index, `Epsilon - at index ${index}`)
271
+ index = twoByteString.indexOf('\u0392', 0, 'ucs2')
272
+ t.equal(-1, index, `Not beta - at index ${index}`)
273
+
274
+ // Test multi-char pattern
275
+ index = twoByteString.indexOf('\u039a\u0391', 0, 'ucs2')
276
+ t.equal(0, index, `Lambda Alpha - at index ${index}`)
277
+ index = twoByteString.indexOf('\u0391\u03a3', 0, 'ucs2')
278
+ t.equal(2, index, `Alpha Sigma - at index ${index}`)
279
+ index = twoByteString.indexOf('\u03a3\u03a3', 0, 'ucs2')
280
+ t.equal(4, index, `Sigma Sigma - at index ${index}`)
281
+ index = twoByteString.indexOf('\u03a3\u0395', 0, 'ucs2')
282
+ t.equal(6, index, `Sigma Epsilon - at index ${index}`)
283
+ }
284
+
285
+ const mixedByteStringUtf8 = Buffer.from('\u039a\u0391abc\u03a3\u03a3\u0395')
286
+ t.equal(5, mixedByteStringUtf8.indexOf('bc'))
287
+ t.equal(5, mixedByteStringUtf8.indexOf('bc', 5))
288
+ t.equal(5, mixedByteStringUtf8.indexOf('bc', -8))
289
+ t.equal(7, mixedByteStringUtf8.indexOf('\u03a3'))
290
+ t.equal(-1, mixedByteStringUtf8.indexOf('\u0396'))
291
+
292
+
293
+ // Test complex string indexOf algorithms. Only trigger for long strings.
294
+ // Long string that isn't a simple repeat of a shorter string.
295
+ let longString = 'A'
296
+ for (let i = 66; i < 76; i++) { // from 'B' to 'K'
297
+ longString = longString + String.fromCharCode(i) + longString
298
+ }
299
+
300
+ const longBufferString = Buffer.from(longString)
301
+
302
+ // pattern of 15 chars, repeated every 16 chars in long
303
+ let pattern = 'ABACABADABACABA'
304
+ for (let i = 0; i < longBufferString.length - pattern.length; i += 7) {
305
+ const index = longBufferString.indexOf(pattern, i)
306
+ t.equal((i + 15) & ~0xf, index,
307
+ `Long ABACABA...-string at index ${i}`)
308
+ }
309
+
310
+ let index = longBufferString.indexOf('AJABACA')
311
+ t.equal(510, index, `Long AJABACA, First J - at index ${index}`)
312
+ index = longBufferString.indexOf('AJABACA', 511)
313
+ t.equal(1534, index, `Long AJABACA, Second J - at index ${index}`)
314
+
315
+ pattern = 'JABACABADABACABA'
316
+ index = longBufferString.indexOf(pattern)
317
+ t.equal(511, index, `Long JABACABA..., First J - at index ${index}`)
318
+ index = longBufferString.indexOf(pattern, 512)
319
+ t.equal(
320
+ 1535, index, `Long JABACABA..., Second J - at index ${index}`)
321
+
322
+ // Search for a non-ASCII string in a pure ASCII string.
323
+ const asciiString = Buffer.from(
324
+ 'arglebargleglopglyfarglebargleglopglyfarglebargleglopglyf')
325
+ t.equal(-1, asciiString.indexOf('\x2061'))
326
+ t.equal(3, asciiString.indexOf('leb', 0))
327
+
328
+ // Search in string containing many non-ASCII chars.
329
+ const allCodePoints = []
330
+ for (let i = 0; i < 65536; i++) allCodePoints[i] = i
331
+ const allCharsString = String.fromCharCode.apply(String, allCodePoints)
332
+ const allCharsBufferUtf8 = Buffer.from(allCharsString)
333
+ const allCharsBufferUcs2 = Buffer.from(allCharsString, 'ucs2')
334
+
335
+ // Search for string long enough to trigger complex search with ASCII pattern
336
+ // and UC16 subject.
337
+ t.equal(-1, allCharsBufferUtf8.indexOf('notfound'))
338
+ t.equal(-1, allCharsBufferUcs2.indexOf('notfound'))
339
+
340
+ // Needle is longer than haystack, but only because it's encoded as UTF-16
341
+ t.equal(Buffer.from('aaaa').indexOf('a'.repeat(4), 'ucs2'), -1)
342
+
343
+ t.equal(Buffer.from('aaaa').indexOf('a'.repeat(4), 'utf8'), 0)
344
+ t.equal(Buffer.from('aaaa').indexOf('你好', 'ucs2'), -1)
345
+
346
+ // Haystack has odd length, but the needle is UCS2.
347
+ t.equal(Buffer.from('aaaaa').indexOf('b', 'ucs2'), -1)
348
+
349
+ {
350
+ // Find substrings in Utf8.
351
+ const lengths = [1, 3, 15]; // Single char, simple and complex.
352
+ const indices = [0x5, 0x60, 0x400, 0x680, 0x7ee, 0xFF02, 0x16610, 0x2f77b]
353
+ for (let lengthIndex = 0; lengthIndex < lengths.length; lengthIndex++) {
354
+ for (let i = 0; i < indices.length; i++) {
355
+ const index = indices[i]
356
+ let length = lengths[lengthIndex]
357
+
358
+ if (index + length > 0x7F) {
359
+ length = 2 * length
360
+ }
361
+
362
+ if (index + length > 0x7FF) {
363
+ length = 3 * length
364
+ }
365
+
366
+ if (index + length > 0xFFFF) {
367
+ length = 4 * length
368
+ }
369
+
370
+ const patternBufferUtf8 = allCharsBufferUtf8.slice(index, index + length)
371
+ t.equal(index, allCharsBufferUtf8.indexOf(patternBufferUtf8))
372
+
373
+ const patternStringUtf8 = patternBufferUtf8.toString()
374
+ t.equal(index, allCharsBufferUtf8.indexOf(patternStringUtf8))
375
+ }
376
+ }
377
+ }
378
+
379
+ {
380
+ // Find substrings in Usc2.
381
+ const lengths = [2, 4, 16]; // Single char, simple and complex.
382
+ const indices = [0x5, 0x65, 0x105, 0x205, 0x285, 0x2005, 0x2085, 0xfff0]
383
+ for (let lengthIndex = 0; lengthIndex < lengths.length; lengthIndex++) {
384
+ for (let i = 0; i < indices.length; i++) {
385
+ const index = indices[i] * 2
386
+ const length = lengths[lengthIndex]
387
+
388
+ const patternBufferUcs2 =
389
+ allCharsBufferUcs2.slice(index, index + length)
390
+ t.equal(
391
+ index, allCharsBufferUcs2.indexOf(patternBufferUcs2, 0, 'ucs2'))
392
+
393
+ const patternStringUcs2 = patternBufferUcs2.toString('ucs2')
394
+ t.equal(
395
+ index, allCharsBufferUcs2.indexOf(patternStringUcs2, 0, 'ucs2'))
396
+ }
397
+ }
398
+ }
399
+
400
+ [
401
+ () => {},
402
+ {},
403
+ []
404
+ ].forEach(val => {
405
+ debugger
406
+ t.throws(() => b.indexOf(val), TypeError, `"${JSON.stringify(val)}" should throw`)
407
+ })
408
+
409
+ // Test weird offset arguments.
410
+ // The following offsets coerce to NaN or 0, searching the whole Buffer
411
+ t.equal(b.indexOf('b', undefined), 1)
412
+ t.equal(b.indexOf('b', {}), 1)
413
+ t.equal(b.indexOf('b', 0), 1)
414
+ t.equal(b.indexOf('b', null), 1)
415
+ t.equal(b.indexOf('b', []), 1)
416
+
417
+ // The following offset coerces to 2, in other words +[2] === 2
418
+ t.equal(b.indexOf('b', [2]), -1)
419
+
420
+ // Behavior should match String.indexOf()
421
+ t.equal(
422
+ b.indexOf('b', undefined),
423
+ stringComparison.indexOf('b', undefined))
424
+ t.equal(
425
+ b.indexOf('b', {}),
426
+ stringComparison.indexOf('b', {}))
427
+ t.equal(
428
+ b.indexOf('b', 0),
429
+ stringComparison.indexOf('b', 0))
430
+ t.equal(
431
+ b.indexOf('b', null),
432
+ stringComparison.indexOf('b', null))
433
+ t.equal(
434
+ b.indexOf('b', []),
435
+ stringComparison.indexOf('b', []))
436
+ t.equal(
437
+ b.indexOf('b', [2]),
438
+ stringComparison.indexOf('b', [2]))
439
+
440
+ // test truncation of Number arguments to uint8
441
+ {
442
+ const buf = Buffer.from('this is a test')
443
+ t.equal(buf.indexOf(0x6973), 3)
444
+ t.equal(buf.indexOf(0x697320), 4)
445
+ t.equal(buf.indexOf(0x69732069), 2)
446
+ t.equal(buf.indexOf(0x697374657374), 0)
447
+ t.equal(buf.indexOf(0x69737374), 0)
448
+ t.equal(buf.indexOf(0x69737465), 11)
449
+ t.equal(buf.indexOf(0x69737465), 11)
450
+ t.equal(buf.indexOf(-140), 0)
451
+ t.equal(buf.indexOf(-152), 1)
452
+ t.equal(buf.indexOf(0xff), -1)
453
+ t.equal(buf.indexOf(0xffff), -1)
454
+ }
455
+
456
+ // Test that Uint8Array arguments are okay.
457
+ {
458
+ const needle = new Uint8Array([ 0x66, 0x6f, 0x6f ])
459
+ const haystack = new BufferList(Buffer.from('a foo b foo'))
460
+ t.equal(haystack.indexOf(needle), 2)
461
+ }
462
+ t.end()
463
+ })
package/test/test.js CHANGED
@@ -11,16 +11,20 @@ var tape = require('tape')
11
11
  ('hex utf8 utf-8 ascii binary base64'
12
12
  + (process.browser ? '' : ' ucs2 ucs-2 utf16le utf-16le')).split(' ')
13
13
 
14
+ // run the indexOf tests
15
+ require('./indexOf')
16
+
14
17
  tape('single bytes from single buffer', function (t) {
15
18
  var bl = new BufferList()
16
19
  bl.append(Buffer.from('abcd'))
17
20
 
18
21
  t.equal(bl.length, 4)
19
-
22
+ t.equal(bl.get(-1), undefined)
20
23
  t.equal(bl.get(0), 97)
21
24
  t.equal(bl.get(1), 98)
22
25
  t.equal(bl.get(2), 99)
23
26
  t.equal(bl.get(3), 100)
27
+ t.equal(bl.get(4), undefined)
24
28
 
25
29
  t.end()
26
30
  })
@@ -427,453 +431,19 @@ tape('test toString encoding', function (t) {
427
431
  t.end()
428
432
  })
429
433
 
430
- tape('indexOf single byte needle', t => {
431
- const bl = new BufferList(['abcdefg', 'abcdefg', '12345'])
432
- t.equal(bl.indexOf('e'), 4)
433
- t.equal(bl.indexOf('e', 5), 11)
434
- t.equal(bl.indexOf('e', 12), -1)
435
- t.equal(bl.indexOf('5'), 18)
436
- t.end()
437
- })
438
-
439
- tape('indexOf multiple byte needle', t => {
440
- const bl = new BufferList(['abcdefg', 'abcdefg'])
441
- t.equal(bl.indexOf('ef'), 4)
442
- t.equal(bl.indexOf('ef', 5), 11)
443
- t.end()
444
- })
445
-
446
- tape('indexOf multiple byte needles across buffer boundaries', t => {
447
- const bl = new BufferList(['abcdefg', 'abcdefg'])
448
- t.equal(bl.indexOf('fgabc'), 5)
449
- t.end()
450
- })
451
-
452
- tape('indexOf takes a buffer list search', t => {
453
- const bl = new BufferList(['abcdefg', 'abcdefg'])
454
- const search = new BufferList('fgabc')
455
- t.equal(bl.indexOf(search), 5)
456
- t.end()
457
- })
458
-
459
- tape('indexOf a zero byte needle', t => {
460
- const b = new BufferList('abcdef')
461
- const buf_empty = Buffer.from('')
462
- t.equal(b.indexOf(''), 0)
463
- t.equal(b.indexOf('', 1), 1)
464
- t.equal(b.indexOf('', b.length + 1), b.length)
465
- t.equal(b.indexOf('', Infinity), b.length)
466
- t.equal(b.indexOf(buf_empty), 0)
467
- t.equal(b.indexOf(buf_empty, 1), 1)
468
- t.equal(b.indexOf(buf_empty, b.length + 1), b.length)
469
- t.equal(b.indexOf(buf_empty, Infinity), b.length)
470
- t.end()
471
- })
472
-
473
- // only present in node 6+
474
- ;(process.version.substr(1).split('.')[0] >= 6) && tape('indexOf latin1 and binary encoding', t => {
475
- const b = new BufferList('abcdef')
476
-
477
- // test latin1 encoding
478
- t.equal(
479
- new BufferList(Buffer.from(b.toString('latin1'), 'latin1'))
480
- .indexOf('d', 0, 'latin1'),
481
- 3
482
- )
483
- t.equal(
484
- new BufferList(Buffer.from(b.toString('latin1'), 'latin1'))
485
- .indexOf(Buffer.from('d', 'latin1'), 0, 'latin1'),
486
- 3
487
- )
488
- t.equal(
489
- new BufferList(Buffer.from('aa\u00e8aa', 'latin1'))
490
- .indexOf('\u00e8', 'latin1'),
491
- 2
492
- )
493
- t.equal(
494
- new BufferList(Buffer.from('\u00e8', 'latin1'))
495
- .indexOf('\u00e8', 'latin1'),
496
- 0
497
- )
498
- t.equal(
499
- new BufferList(Buffer.from('\u00e8', 'latin1'))
500
- .indexOf(Buffer.from('\u00e8', 'latin1'), 'latin1'),
501
- 0
502
- )
503
-
504
- // test binary encoding
505
- t.equal(
506
- new BufferList(Buffer.from(b.toString('binary'), 'binary'))
507
- .indexOf('d', 0, 'binary'),
508
- 3
509
- )
510
- t.equal(
511
- new BufferList(Buffer.from(b.toString('binary'), 'binary'))
512
- .indexOf(Buffer.from('d', 'binary'), 0, 'binary'),
513
- 3
514
- )
515
- t.equal(
516
- new BufferList(Buffer.from('aa\u00e8aa', 'binary'))
517
- .indexOf('\u00e8', 'binary'),
518
- 2
519
- )
520
- t.equal(
521
- new BufferList(Buffer.from('\u00e8', 'binary'))
522
- .indexOf('\u00e8', 'binary'),
523
- 0
524
- )
525
- t.equal(
526
- new BufferList(Buffer.from('\u00e8', 'binary'))
527
- .indexOf(Buffer.from('\u00e8', 'binary'), 'binary'),
528
- 0
529
- )
530
- t.end()
531
- })
532
-
533
- tape('indexOf the entire nodejs10 buffer test suite', t => {
534
- const b = new BufferList('abcdef')
535
- const buf_a = Buffer.from('a')
536
- const buf_bc = Buffer.from('bc')
537
- const buf_f = Buffer.from('f')
538
- const buf_z = Buffer.from('z')
539
-
540
- const stringComparison = 'abcdef'
541
-
542
- t.equal(b.indexOf('a'), 0)
543
- t.equal(b.indexOf('a', 1), -1)
544
- t.equal(b.indexOf('a', -1), -1)
545
- t.equal(b.indexOf('a', -4), -1)
546
- t.equal(b.indexOf('a', -b.length), 0)
547
- t.equal(b.indexOf('a', NaN), 0)
548
- t.equal(b.indexOf('a', -Infinity), 0)
549
- t.equal(b.indexOf('a', Infinity), -1)
550
- t.equal(b.indexOf('bc'), 1)
551
- t.equal(b.indexOf('bc', 2), -1)
552
- t.equal(b.indexOf('bc', -1), -1)
553
- t.equal(b.indexOf('bc', -3), -1)
554
- t.equal(b.indexOf('bc', -5), 1)
555
- t.equal(b.indexOf('bc', NaN), 1)
556
- t.equal(b.indexOf('bc', -Infinity), 1)
557
- t.equal(b.indexOf('bc', Infinity), -1)
558
- t.equal(b.indexOf('f'), b.length - 1)
559
- t.equal(b.indexOf('z'), -1)
560
- // empty search tests
561
- t.equal(b.indexOf(buf_a), 0)
562
- t.equal(b.indexOf(buf_a, 1), -1)
563
- t.equal(b.indexOf(buf_a, -1), -1)
564
- t.equal(b.indexOf(buf_a, -4), -1)
565
- t.equal(b.indexOf(buf_a, -b.length), 0)
566
- t.equal(b.indexOf(buf_a, NaN), 0)
567
- t.equal(b.indexOf(buf_a, -Infinity), 0)
568
- t.equal(b.indexOf(buf_a, Infinity), -1)
569
- t.equal(b.indexOf(buf_bc), 1)
570
- t.equal(b.indexOf(buf_bc, 2), -1)
571
- t.equal(b.indexOf(buf_bc, -1), -1)
572
- t.equal(b.indexOf(buf_bc, -3), -1)
573
- t.equal(b.indexOf(buf_bc, -5), 1)
574
- t.equal(b.indexOf(buf_bc, NaN), 1)
575
- t.equal(b.indexOf(buf_bc, -Infinity), 1)
576
- t.equal(b.indexOf(buf_bc, Infinity), -1)
577
- t.equal(b.indexOf(buf_f), b.length - 1)
578
- t.equal(b.indexOf(buf_z), -1)
579
- t.equal(b.indexOf(0x61), 0)
580
- t.equal(b.indexOf(0x61, 1), -1)
581
- t.equal(b.indexOf(0x61, -1), -1)
582
- t.equal(b.indexOf(0x61, -4), -1)
583
- t.equal(b.indexOf(0x61, -b.length), 0)
584
- t.equal(b.indexOf(0x61, NaN), 0)
585
- t.equal(b.indexOf(0x61, -Infinity), 0)
586
- t.equal(b.indexOf(0x61, Infinity), -1)
587
- t.equal(b.indexOf(0x0), -1)
588
-
589
- // test offsets
590
- t.equal(b.indexOf('d', 2), 3)
591
- t.equal(b.indexOf('f', 5), 5)
592
- t.equal(b.indexOf('f', -1), 5)
593
- t.equal(b.indexOf('f', 6), -1)
594
-
595
- t.equal(b.indexOf(Buffer.from('d'), 2), 3)
596
- t.equal(b.indexOf(Buffer.from('f'), 5), 5)
597
- t.equal(b.indexOf(Buffer.from('f'), -1), 5)
598
- t.equal(b.indexOf(Buffer.from('f'), 6), -1)
599
-
600
- t.equal(Buffer.from('ff').indexOf(Buffer.from('f'), 1, 'ucs2'), -1)
601
-
602
- // test invalid and uppercase encoding
603
- t.equal(b.indexOf('b', 'utf8'), 1)
604
- t.equal(b.indexOf('b', 'UTF8'), 1)
605
- t.equal(b.indexOf('62', 'HEX'), 1)
606
- t.throws(() => b.indexOf('bad', 'enc'), TypeError)
607
-
608
- // test hex encoding
609
- t.equal(
610
- Buffer.from(b.toString('hex'), 'hex')
611
- .indexOf('64', 0, 'hex'),
612
- 3
613
- )
614
- t.equal(
615
- Buffer.from(b.toString('hex'), 'hex')
616
- .indexOf(Buffer.from('64', 'hex'), 0, 'hex'),
617
- 3
618
- )
619
-
620
- // test base64 encoding
621
- t.equal(
622
- Buffer.from(b.toString('base64'), 'base64')
623
- .indexOf('ZA==', 0, 'base64'),
624
- 3
625
- )
626
- t.equal(
627
- Buffer.from(b.toString('base64'), 'base64')
628
- .indexOf(Buffer.from('ZA==', 'base64'), 0, 'base64'),
629
- 3
630
- )
631
-
632
- // test ascii encoding
633
- t.equal(
634
- Buffer.from(b.toString('ascii'), 'ascii')
635
- .indexOf('d', 0, 'ascii'),
636
- 3
637
- )
638
- t.equal(
639
- Buffer.from(b.toString('ascii'), 'ascii')
640
- .indexOf(Buffer.from('d', 'ascii'), 0, 'ascii'),
641
- 3
642
- )
643
-
644
- // test optional offset with passed encoding
645
- t.equal(Buffer.from('aaaa0').indexOf('30', 'hex'), 4)
646
- t.equal(Buffer.from('aaaa00a').indexOf('3030', 'hex'), 4)
647
-
648
- {
649
- // test usc2 encoding
650
- const twoByteString = Buffer.from('\u039a\u0391\u03a3\u03a3\u0395', 'ucs2')
651
-
652
- t.equal(8, twoByteString.indexOf('\u0395', 4, 'ucs2'))
653
- t.equal(6, twoByteString.indexOf('\u03a3', -4, 'ucs2'))
654
- t.equal(4, twoByteString.indexOf('\u03a3', -6, 'ucs2'))
655
- t.equal(4, twoByteString.indexOf(
656
- Buffer.from('\u03a3', 'ucs2'), -6, 'ucs2'))
657
- t.equal(-1, twoByteString.indexOf('\u03a3', -2, 'ucs2'))
658
- }
659
-
660
- const mixedByteStringUcs2 =
661
- Buffer.from('\u039a\u0391abc\u03a3\u03a3\u0395', 'ucs2')
662
- t.equal(6, mixedByteStringUcs2.indexOf('bc', 0, 'ucs2'))
663
- t.equal(10, mixedByteStringUcs2.indexOf('\u03a3', 0, 'ucs2'))
664
- t.equal(-1, mixedByteStringUcs2.indexOf('\u0396', 0, 'ucs2'))
665
-
666
- t.equal(
667
- 6, mixedByteStringUcs2.indexOf(Buffer.from('bc', 'ucs2'), 0, 'ucs2'))
668
- t.equal(
669
- 10, mixedByteStringUcs2.indexOf(Buffer.from('\u03a3', 'ucs2'), 0, 'ucs2'))
670
- t.equal(
671
- -1, mixedByteStringUcs2.indexOf(Buffer.from('\u0396', 'ucs2'), 0, 'ucs2'))
672
-
673
- {
674
- const twoByteString = Buffer.from('\u039a\u0391\u03a3\u03a3\u0395', 'ucs2')
675
-
676
- // Test single char pattern
677
- t.equal(0, twoByteString.indexOf('\u039a', 0, 'ucs2'))
678
- let index = twoByteString.indexOf('\u0391', 0, 'ucs2')
679
- t.equal(2, index, `Alpha - at index ${index}`)
680
- index = twoByteString.indexOf('\u03a3', 0, 'ucs2')
681
- t.equal(4, index, `First Sigma - at index ${index}`)
682
- index = twoByteString.indexOf('\u03a3', 6, 'ucs2')
683
- t.equal(6, index, `Second Sigma - at index ${index}`)
684
- index = twoByteString.indexOf('\u0395', 0, 'ucs2')
685
- t.equal(8, index, `Epsilon - at index ${index}`)
686
- index = twoByteString.indexOf('\u0392', 0, 'ucs2')
687
- t.equal(-1, index, `Not beta - at index ${index}`)
688
-
689
- // Test multi-char pattern
690
- index = twoByteString.indexOf('\u039a\u0391', 0, 'ucs2')
691
- t.equal(0, index, `Lambda Alpha - at index ${index}`)
692
- index = twoByteString.indexOf('\u0391\u03a3', 0, 'ucs2')
693
- t.equal(2, index, `Alpha Sigma - at index ${index}`)
694
- index = twoByteString.indexOf('\u03a3\u03a3', 0, 'ucs2')
695
- t.equal(4, index, `Sigma Sigma - at index ${index}`)
696
- index = twoByteString.indexOf('\u03a3\u0395', 0, 'ucs2')
697
- t.equal(6, index, `Sigma Epsilon - at index ${index}`)
698
- }
699
-
700
- const mixedByteStringUtf8 = Buffer.from('\u039a\u0391abc\u03a3\u03a3\u0395')
701
- t.equal(5, mixedByteStringUtf8.indexOf('bc'))
702
- t.equal(5, mixedByteStringUtf8.indexOf('bc', 5))
703
- t.equal(5, mixedByteStringUtf8.indexOf('bc', -8))
704
- t.equal(7, mixedByteStringUtf8.indexOf('\u03a3'))
705
- t.equal(-1, mixedByteStringUtf8.indexOf('\u0396'))
706
-
707
-
708
- // Test complex string indexOf algorithms. Only trigger for long strings.
709
- // Long string that isn't a simple repeat of a shorter string.
710
- let longString = 'A'
711
- for (let i = 66; i < 76; i++) { // from 'B' to 'K'
712
- longString = longString + String.fromCharCode(i) + longString
713
- }
714
-
715
- const longBufferString = Buffer.from(longString)
716
-
717
- // pattern of 15 chars, repeated every 16 chars in long
718
- let pattern = 'ABACABADABACABA'
719
- for (let i = 0; i < longBufferString.length - pattern.length; i += 7) {
720
- const index = longBufferString.indexOf(pattern, i)
721
- t.equal((i + 15) & ~0xf, index,
722
- `Long ABACABA...-string at index ${i}`)
723
- }
724
-
725
- let index = longBufferString.indexOf('AJABACA')
726
- t.equal(510, index, `Long AJABACA, First J - at index ${index}`)
727
- index = longBufferString.indexOf('AJABACA', 511)
728
- t.equal(1534, index, `Long AJABACA, Second J - at index ${index}`)
729
-
730
- pattern = 'JABACABADABACABA'
731
- index = longBufferString.indexOf(pattern)
732
- t.equal(511, index, `Long JABACABA..., First J - at index ${index}`)
733
- index = longBufferString.indexOf(pattern, 512)
734
- t.equal(
735
- 1535, index, `Long JABACABA..., Second J - at index ${index}`)
736
-
737
- // Search for a non-ASCII string in a pure ASCII string.
738
- const asciiString = Buffer.from(
739
- 'arglebargleglopglyfarglebargleglopglyfarglebargleglopglyf')
740
- t.equal(-1, asciiString.indexOf('\x2061'))
741
- t.equal(3, asciiString.indexOf('leb', 0))
742
-
743
- // Search in string containing many non-ASCII chars.
744
- const allCodePoints = []
745
- for (let i = 0; i < 65536; i++) allCodePoints[i] = i
746
- const allCharsString = String.fromCharCode.apply(String, allCodePoints)
747
- const allCharsBufferUtf8 = Buffer.from(allCharsString)
748
- const allCharsBufferUcs2 = Buffer.from(allCharsString, 'ucs2')
749
-
750
- // Search for string long enough to trigger complex search with ASCII pattern
751
- // and UC16 subject.
752
- t.equal(-1, allCharsBufferUtf8.indexOf('notfound'))
753
- t.equal(-1, allCharsBufferUcs2.indexOf('notfound'))
754
-
755
- // Needle is longer than haystack, but only because it's encoded as UTF-16
756
- t.equal(Buffer.from('aaaa').indexOf('a'.repeat(4), 'ucs2'), -1)
757
-
758
- t.equal(Buffer.from('aaaa').indexOf('a'.repeat(4), 'utf8'), 0)
759
- t.equal(Buffer.from('aaaa').indexOf('你好', 'ucs2'), -1)
760
-
761
- // Haystack has odd length, but the needle is UCS2.
762
- t.equal(Buffer.from('aaaaa').indexOf('b', 'ucs2'), -1)
763
-
764
- {
765
- // Find substrings in Utf8.
766
- const lengths = [1, 3, 15]; // Single char, simple and complex.
767
- const indices = [0x5, 0x60, 0x400, 0x680, 0x7ee, 0xFF02, 0x16610, 0x2f77b]
768
- for (let lengthIndex = 0; lengthIndex < lengths.length; lengthIndex++) {
769
- for (let i = 0; i < indices.length; i++) {
770
- const index = indices[i]
771
- let length = lengths[lengthIndex]
772
-
773
- if (index + length > 0x7F) {
774
- length = 2 * length
775
- }
776
-
777
- if (index + length > 0x7FF) {
778
- length = 3 * length
779
- }
780
-
781
- if (index + length > 0xFFFF) {
782
- length = 4 * length
783
- }
784
-
785
- const patternBufferUtf8 = allCharsBufferUtf8.slice(index, index + length)
786
- t.equal(index, allCharsBufferUtf8.indexOf(patternBufferUtf8))
787
-
788
- const patternStringUtf8 = patternBufferUtf8.toString()
789
- t.equal(index, allCharsBufferUtf8.indexOf(patternStringUtf8))
790
- }
434
+ tape('uninitialized memory', function (t) {
435
+ const secret = crypto.randomBytes(256)
436
+ for (let i = 0; i < 1e6; i++) {
437
+ const clone = Buffer.from(secret)
438
+ const bl = new BufferList()
439
+ bl.append(Buffer.from('a'))
440
+ bl.consume(-1024)
441
+ const buf = bl.slice(1)
442
+ if (buf.indexOf(clone) !== -1) {
443
+ t.fail(`Match (at ${i})`)
444
+ break
791
445
  }
792
446
  }
793
-
794
- {
795
- // Find substrings in Usc2.
796
- const lengths = [2, 4, 16]; // Single char, simple and complex.
797
- const indices = [0x5, 0x65, 0x105, 0x205, 0x285, 0x2005, 0x2085, 0xfff0]
798
- for (let lengthIndex = 0; lengthIndex < lengths.length; lengthIndex++) {
799
- for (let i = 0; i < indices.length; i++) {
800
- const index = indices[i] * 2
801
- const length = lengths[lengthIndex]
802
-
803
- const patternBufferUcs2 =
804
- allCharsBufferUcs2.slice(index, index + length)
805
- t.equal(
806
- index, allCharsBufferUcs2.indexOf(patternBufferUcs2, 0, 'ucs2'))
807
-
808
- const patternStringUcs2 = patternBufferUcs2.toString('ucs2')
809
- t.equal(
810
- index, allCharsBufferUcs2.indexOf(patternStringUcs2, 0, 'ucs2'))
811
- }
812
- }
813
- }
814
-
815
- [
816
- () => {},
817
- {},
818
- []
819
- ].forEach(val => {
820
- debugger
821
- t.throws(() => b.indexOf(val), TypeError, `"${JSON.stringify(val)}" should throw`)
822
- })
823
-
824
- // Test weird offset arguments.
825
- // The following offsets coerce to NaN or 0, searching the whole Buffer
826
- t.equal(b.indexOf('b', undefined), 1)
827
- t.equal(b.indexOf('b', {}), 1)
828
- t.equal(b.indexOf('b', 0), 1)
829
- t.equal(b.indexOf('b', null), 1)
830
- t.equal(b.indexOf('b', []), 1)
831
-
832
- // The following offset coerces to 2, in other words +[2] === 2
833
- t.equal(b.indexOf('b', [2]), -1)
834
-
835
- // Behavior should match String.indexOf()
836
- t.equal(
837
- b.indexOf('b', undefined),
838
- stringComparison.indexOf('b', undefined))
839
- t.equal(
840
- b.indexOf('b', {}),
841
- stringComparison.indexOf('b', {}))
842
- t.equal(
843
- b.indexOf('b', 0),
844
- stringComparison.indexOf('b', 0))
845
- t.equal(
846
- b.indexOf('b', null),
847
- stringComparison.indexOf('b', null))
848
- t.equal(
849
- b.indexOf('b', []),
850
- stringComparison.indexOf('b', []))
851
- t.equal(
852
- b.indexOf('b', [2]),
853
- stringComparison.indexOf('b', [2]))
854
-
855
- // test truncation of Number arguments to uint8
856
- {
857
- const buf = Buffer.from('this is a test')
858
- t.equal(buf.indexOf(0x6973), 3)
859
- t.equal(buf.indexOf(0x697320), 4)
860
- t.equal(buf.indexOf(0x69732069), 2)
861
- t.equal(buf.indexOf(0x697374657374), 0)
862
- t.equal(buf.indexOf(0x69737374), 0)
863
- t.equal(buf.indexOf(0x69737465), 11)
864
- t.equal(buf.indexOf(0x69737465), 11)
865
- t.equal(buf.indexOf(-140), 0)
866
- t.equal(buf.indexOf(-152), 1)
867
- t.equal(buf.indexOf(0xff), -1)
868
- t.equal(buf.indexOf(0xffff), -1)
869
- }
870
-
871
- // Test that Uint8Array arguments are okay.
872
- {
873
- const needle = new Uint8Array([ 0x66, 0x6f, 0x6f ])
874
- const haystack = new BufferList(Buffer.from('a foo b foo'))
875
- t.equal(haystack.indexOf(needle), 2)
876
- }
877
447
  t.end()
878
448
  })
879
449
 
@@ -1095,6 +665,20 @@ tape('shallow slice does not make a copy', function (t) {
1095
665
  t.equal(bl.toString(), 'hhhhhhhh')
1096
666
  })
1097
667
 
668
+ tape('shallow slice with 0 length', function (t) {
669
+ t.plan(1)
670
+ var buffers = [Buffer.from('First'), Buffer.from('Second'), Buffer.from('Third')]
671
+ var bl = (new BufferList(buffers)).shallowSlice(0, 0)
672
+ t.equal(bl.length, 0)
673
+ })
674
+
675
+ tape('shallow slice with 0 length from middle', function (t) {
676
+ t.plan(1)
677
+ var buffers = [Buffer.from('First'), Buffer.from('Second'), Buffer.from('Third')]
678
+ var bl = (new BufferList(buffers)).shallowSlice(10, 10)
679
+ t.equal(bl.length, 0)
680
+ })
681
+
1098
682
  tape('duplicate', function (t) {
1099
683
  t.plan(2)
1100
684