bl 0.4.1 → 0.7.0

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/.travis.yml CHANGED
@@ -8,4 +8,8 @@ branches:
8
8
  notifications:
9
9
  email:
10
10
  - rod@vagg.org
11
- script: npm test
11
+ script: npm test
12
+ env:
13
+ global:
14
+ - SAUCE_USER=bl-sauce
15
+ - secure: "EN/BSk+c4E8pgtW/hTSk5dp3iBng6PPtWHc2kxeMyUjMCYTjD4/zgZXm/gPTcuBxWByDlFrHlJ9A6L+aj5r9n/48tBJJLJ6B2WezZMAnzo4HHzl445BmSI6MbqmUbrN3nQ+lmRXIUzatW+pyoP+DWgCcLJpXtdKN7LwgIxIQS2g="
package/README.md CHANGED
@@ -84,6 +84,8 @@ bl.pipe(fs.createWriteStream('gibberish.txt'))
84
84
  * <a href="#append"><code>bl.<b>append(buffer)</b></code></a>
85
85
  * <a href="#get"><code>bl.<b>get(index)</b></code></a>
86
86
  * <a href="#slice"><code>bl.<b>slice([ start[, end ] ])</b></code></a>
87
+ * <a href="#copy"><code>bl.<b>copy(dest, [ destStart, [ srcStart [, srcEnd ] ] ])</b></code></a>
88
+ * <a href="#duplicate"><code>bl.<b>duplicate()</b></code></a>
87
89
  * <a href="#consume"><code>bl.<b>consume(bytes)</b></code></a>
88
90
  * <a href="#toString"><code>bl.<b>toString([encoding, [ start, [ end ]]])</b></code></a>
89
91
  * <a href="#readXX"><code>bl.<b>readDoubleBE()</b></code>, <code>bl.<b>readDoubleLE()</b></code>, <code>bl.<b>readFloatBE()</b></code>, <code>bl.<b>readFloatLE()</b></code>, <code>bl.<b>readInt32BE()</b></code>, <code>bl.<b>readInt32LE()</b></code>, <code>bl.<b>readUInt32BE()</b></code>, <code>bl.<b>readUInt32LE()</b></code>, <code>bl.<b>readInt16BE()</b></code>, <code>bl.<b>readInt16LE()</b></code>, <code>bl.<b>readUInt16BE()</b></code>, <code>bl.<b>readUInt16LE()</b></code>, <code>bl.<b>readInt8()</b></code>, <code>bl.<b>readUInt8()</b></code></a>
@@ -130,6 +132,28 @@ Get the length of the list in bytes. This is the sum of the lengths of all of th
130
132
 
131
133
  If the requested range spans a single internal buffer then a slice of that buffer will be returned which shares the original memory range of that Buffer. If the range spans multiple buffers then copy operations will likely occur to give you a uniform Buffer.
132
134
 
135
+ --------------------------------------------------------
136
+ <a name="copy"></a>
137
+ ### bl.copy(dest, [ destStart, [ srcStart [, srcEnd ] ] ])
138
+ `copy()` copies the content of the list in the `dest` buffer, starting from `destStart` and containing the bytes within the range specified with `srcStart` to `srcEnd`. `destStart`, `start` and `end` are optional and will default to the beginning of the `dest` buffer, and the beginning and end of the list respectively.
139
+
140
+ --------------------------------------------------------
141
+ <a name="duplicate"></a>
142
+ ### bl.duplicate()
143
+ `duplicate()` performs a **shallow-copy** of the list. The internal Buffers remains the same, so if you change the underlying Buffers, the change will be reflected in both the original and the duplicate. This method is needed if you want to call `consume()` or `pipe()` and still keep the original list.Example:
144
+
145
+ ```js
146
+ var bl = new BufferList()
147
+
148
+ bl.append('hello')
149
+ bl.append(' world')
150
+ bl.append('\n')
151
+
152
+ bl.duplicate().pipe(process.stdout, { end: false })
153
+
154
+ console.log(bl.toString())
155
+ ```
156
+
133
157
  --------------------------------------------------------
134
158
  <a name="consume"></a>
135
159
  ### bl.consume(bytes)
@@ -153,6 +177,17 @@ See the <b><code>[Buffer](http://nodejs.org/docs/latest/api/buffer.html)</code><
153
177
  ### Streams
154
178
  **bl** is a Node **[Duplex Stream](http://nodejs.org/docs/latest/api/stream.html#stream_class_stream_duplex)**, so it can be read from and written to like a standard Node stream. You can also `pipe()` to and from a **bl** instance.
155
179
 
180
+ --------------------------------------------------------
181
+
182
+ ## Contributors
183
+
184
+ **bl** is brought to you by the following hackers:
185
+
186
+ * [Rod Vagg](https://github.com/rvagg)
187
+ * [Matteo Collina](https://github.com/mcollina)
188
+
189
+ =======
190
+
156
191
  ## License
157
192
 
158
- **bl** is Copyright (c) 2013 Rod Vagg [@rvagg](https://twitter.com/rvagg) and licenced under the MIT licence. All rights not explicitly granted in the MIT license are reserved. See the included LICENSE file for more details.
193
+ **bl** is Copyright (c) 2013 Rod Vagg [@rvagg](https://twitter.com/rvagg) and licenced under the MIT licence. All rights not explicitly granted in the MIT license are reserved. See the included LICENSE file for more details.
package/bl.js CHANGED
@@ -1,5 +1,5 @@
1
- const DuplexStream = require('stream').DuplexStream || require('readable-stream/duplex')
2
- , util = require('util')
1
+ var DuplexStream = require('readable-stream').Duplex
2
+ , util = require('util')
3
3
 
4
4
  function BufferList (callback) {
5
5
  if (!(this instanceof BufferList))
@@ -8,8 +8,23 @@ function BufferList (callback) {
8
8
  this._bufs = []
9
9
  this.length = 0
10
10
 
11
- if (typeof callback == 'function')
11
+ if (typeof callback == 'function') {
12
12
  this._callback = callback
13
+
14
+ var piper = function (err) {
15
+ if (this._callback) {
16
+ this._callback(err)
17
+ this._callback = null
18
+ }
19
+ }.bind(this)
20
+
21
+ this.on('pipe', function (src) {
22
+ src.on('error', piper)
23
+ })
24
+ this.on('unpipe', function (src) {
25
+ src.removeListener('error', piper)
26
+ })
27
+ }
13
28
  else if (Buffer.isBuffer(callback))
14
29
  this.append(callback)
15
30
  else if (Array.isArray(callback)) {
@@ -53,9 +68,13 @@ BufferList.prototype._read = function (size) {
53
68
  this.consume(size)
54
69
  }
55
70
 
56
- BufferList.prototype.end = function () {
57
- if (this._callback)
71
+ BufferList.prototype.end = function (chunk) {
72
+ DuplexStream.prototype.end.call(this, chunk)
73
+
74
+ if (this._callback) {
58
75
  this._callback(null, this.slice())
76
+ this._callback = null
77
+ }
59
78
  }
60
79
 
61
80
  BufferList.prototype.get = function (index) {
@@ -63,38 +82,59 @@ BufferList.prototype.get = function (index) {
63
82
  }
64
83
 
65
84
  BufferList.prototype.slice = function (start, end) {
66
- if (typeof start != 'number' || start < 0)
67
- start = 0
68
- if (typeof end != 'number' || end > this.length)
69
- end = this.length
70
- if (start >= this.length)
71
- return new Buffer(0)
72
- if (end <= 0)
73
- return new Buffer(0)
74
-
75
- if (start === 0 && end == this.length)
76
- return Buffer.concat(this._bufs)
77
-
78
- var off = this._offset(start)
79
- , len = end - start
85
+ return this.copy(null, 0, start, end)
86
+ }
87
+
88
+ BufferList.prototype.copy = function (dst, dstStart, srcStart, srcEnd) {
89
+ if (typeof srcStart != 'number' || srcStart < 0)
90
+ srcStart = 0
91
+ if (typeof srcEnd != 'number' || srcEnd > this.length)
92
+ srcEnd = this.length
93
+ if (srcStart >= this.length)
94
+ return dst || new Buffer(0)
95
+ if (srcEnd <= 0)
96
+ return dst || new Buffer(0)
97
+
98
+ var copy = !!dst
99
+ , off = this._offset(srcStart)
100
+ , len = srcEnd - srcStart
80
101
  , bytes = len
81
- , bufoff = 0
82
- , buf, l, i
102
+ , bufoff = (copy && dstStart) || 0
103
+ , start = off[1]
104
+ , l
105
+ , i
106
+
107
+ // copy/slice everything
108
+ if (srcStart === 0 && srcEnd == this.length) {
109
+ if (!copy) // slice, just return a full concat
110
+ return Buffer.concat(this._bufs)
111
+
112
+ // copy, need to copy individual buffers
113
+ for (i = 0; i < this._bufs.length; i++) {
114
+ this._bufs[i].copy(dst, bufoff)
115
+ bufoff += this._bufs[i].length
116
+ }
83
117
 
84
- start = off[1]
118
+ return dst
119
+ }
85
120
 
86
121
  // easy, cheap case where it's a subset of one of the buffers
87
- if (bytes <= this._bufs[off[0]].length - start)
88
- return this._bufs[off[0]].slice(start, start + bytes)
122
+ if (bytes <= this._bufs[off[0]].length - start) {
123
+ return copy
124
+ ? this._bufs[off[0]].copy(dst, dstStart, start, start + bytes)
125
+ : this._bufs[off[0]].slice(start, start + bytes)
126
+ }
89
127
 
90
- buf = new Buffer(len)
128
+ if (!copy) // a slice, we need something to copy in to
129
+ dst = new Buffer(len)
91
130
 
92
131
  for (i = off[0]; i < this._bufs.length; i++) {
93
132
  l = this._bufs[i].length - start
133
+
94
134
  if (bytes > l) {
95
- this._bufs[i].copy(buf, bufoff, start)
135
+ this._bufs[i].copy(dst, bufoff, start)
96
136
  } else {
97
- this._bufs[i].copy(buf, bufoff, start, start + bytes)
137
+ this._bufs[i].copy(dst, bufoff, start, start + bytes)
98
138
  break
99
139
  }
100
140
 
@@ -105,7 +145,7 @@ BufferList.prototype.slice = function (start, end) {
105
145
  start = 0
106
146
  }
107
147
 
108
- return buf
148
+ return dst
109
149
  }
110
150
 
111
151
  BufferList.prototype.toString = function (encoding, start, end) {
@@ -127,6 +167,16 @@ BufferList.prototype.consume = function (bytes) {
127
167
  return this
128
168
  }
129
169
 
170
+ BufferList.prototype.duplicate = function () {
171
+ var i = 0
172
+ , copy = new BufferList()
173
+
174
+ for (; i < this._bufs.length; i++)
175
+ copy.append(this._bufs[i])
176
+
177
+ return copy
178
+ }
179
+
130
180
  ;(function () {
131
181
  var methods = {
132
182
  'readDoubleBE' : 8
@@ -145,11 +195,13 @@ BufferList.prototype.consume = function (bytes) {
145
195
  , 'readUInt8' : 1
146
196
  }
147
197
 
148
- Object.keys(methods).forEach(function (m) {
149
- BufferList.prototype[m] = function (offset) {
150
- return this.slice(offset, offset + methods[m])[m](0)
151
- }
152
- })
198
+ for (var m in methods) {
199
+ (function (m) {
200
+ BufferList.prototype[m] = function (offset) {
201
+ return this.slice(offset, offset + methods[m])[m](0)
202
+ }
203
+ }(m))
204
+ }
153
205
  }())
154
206
 
155
- module.exports = BufferList
207
+ module.exports = BufferList
package/package.json CHANGED
@@ -1,31 +1,42 @@
1
1
  {
2
- "name" : "bl"
3
- , "version" : "0.4.1"
4
- , "description" : "Buffer List: collect buffers and access with a standard readable Buffer interface, streamable too!"
5
- , "main" : "bl.js"
6
- , "scripts" : {
7
- "test": "tape test.js"
8
- }
9
- , "repository" : {
10
- "type" : "git"
11
- , "url" : "https://github.com/rvagg/bl.git"
12
- }
13
- , "homepage" : "https://github.com/rvagg/bl"
14
- , "authors" : [
15
- "Rod Vagg <rod@vagg.org> (https://github.com/rvagg)"
16
- ]
17
- , "keywords" : [
18
- "buffer"
19
- , "buffers"
20
- , "stream"
21
- , "awesomesauce"
22
- ]
23
- , "license" : "MIT"
24
- , "dependencies" : {
25
- "readable-stream" : "~1.0.2"
26
- }
27
- , "devDependencies" : {
28
- "tape" : "*"
29
- , "hash_file" : "*"
30
- }
31
- }
2
+ "name": "bl",
3
+ "version": "0.7.0",
4
+ "description": "Buffer List: collect buffers and access with a standard readable Buffer interface, streamable too!",
5
+ "main": "bl.js",
6
+ "scripts": {
7
+ "test": "node test/test.js | faucet",
8
+ "test-local": "brtapsauce-local test/basic-test.js"
9
+ },
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "https://github.com/rvagg/bl.git"
13
+ },
14
+ "homepage": "https://github.com/rvagg/bl",
15
+ "authors": [
16
+ "Rod Vagg <rod@vagg.org> (https://github.com/rvagg)",
17
+ "Matteo Collina <matteo.collina@gmail.com> (https://github.com/mcollina)"
18
+ ],
19
+ "keywords": [
20
+ "buffer",
21
+ "buffers",
22
+ "stream",
23
+ "awesomesauce"
24
+ ],
25
+ "license": "MIT",
26
+ "dependencies": {
27
+ "readable-stream": "~1.0.2"
28
+ },
29
+ "peerDependencies": {
30
+ "stream-browserify": "*"
31
+ },
32
+ "devDependencies": {
33
+ "tape": "~2.3.2",
34
+ "hash_file": "~0.1.1",
35
+ "brtapsauce": "~0.3.0",
36
+ "faucet": "0.0.0",
37
+ "stream-browserify": "~0.1.2"
38
+ },
39
+ "browser": {
40
+ "readable-stream": "stream-browserify"
41
+ }
42
+ }
@@ -1,8 +1,12 @@
1
- const tape = require('tape')
2
- , crypto = require('crypto')
3
- , fs = require('fs')
4
- , hash = require('hash_file')
5
- , BufferList = require('./')
1
+ var tape = require('tape')
2
+ , crypto = require('crypto')
3
+ , fs = require('fs')
4
+ , hash = require('hash_file')
5
+ , BufferList = require('../')
6
+
7
+ , encodings =
8
+ ('hex utf8 utf-8 ascii binary base64'
9
+ + (process.browser ? '' : ' ucs2 ucs-2 utf16le utf-16le')).split(' ')
6
10
 
7
11
  tape('single bytes from single buffer', function (t) {
8
12
  var bl = new BufferList()
@@ -254,17 +258,15 @@ tape('test toString encoding', function (t) {
254
258
  bl.append(new Buffer('j'))
255
259
  bl.append(new Buffer('\xff\x00'))
256
260
 
257
- 'hex utf8 utf-8 ascii binary base64 ucs2 ucs-2 utf16le utf-16le'
258
- .split(' ')
259
- .forEach(function (enc) {
260
- t.equal(bl.toString(enc), b.toString(enc))
261
+ encodings.forEach(function (enc) {
262
+ t.equal(bl.toString(enc), b.toString(enc), enc)
261
263
  })
262
264
 
263
265
  t.end()
264
266
  })
265
267
 
266
- tape('test stream', function (t) {
267
- var random = crypto.randomBytes(1024 * 1024)
268
+ !process.browser && tape('test stream', function (t) {
269
+ var random = crypto.randomBytes(65534)
268
270
  , rndhash = hash(random, 'md5')
269
271
  , md5sum = crypto.createHash('md5')
270
272
  , bl = new BufferList(function (err, buf) {
@@ -294,9 +296,9 @@ tape('instantiation with Buffer', function (t) {
294
296
  , buf2 = crypto.randomBytes(1024)
295
297
  , b = BufferList(buf)
296
298
 
297
- t.equal(hash(buf, 'md5'), hash(b.slice(), 'md5'), 'same hash!')
299
+ t.equal(buf.toString('hex'), b.slice().toString('hex'), 'same buffer')
298
300
  b = BufferList([ buf, buf2 ])
299
- t.equal(hash(b.slice(), 'md5'), hash(Buffer.concat([ buf, buf2 ]), 'md5'), 'same hash!')
301
+ t.equal(b.slice().toString('hex'), Buffer.concat([ buf, buf2 ]).toString('hex'), 'same buffer')
300
302
  t.end()
301
303
  })
302
304
 
@@ -310,11 +312,131 @@ tape('test String appendage', function (t) {
310
312
  bl.append('j')
311
313
  bl.append('\xff\x00')
312
314
 
313
- 'hex utf8 utf-8 ascii binary base64 ucs2 ucs-2 utf16le utf-16le'
314
- .split(' ')
315
- .forEach(function (enc) {
315
+ encodings.forEach(function (enc) {
316
316
  t.equal(bl.toString(enc), b.toString(enc))
317
317
  })
318
318
 
319
319
  t.end()
320
320
  })
321
+
322
+ tape('write nothing, should get empty buffer', function (t) {
323
+ t.plan(3)
324
+ BufferList(function (err, data) {
325
+ t.notOk(err, 'no error')
326
+ t.ok(Buffer.isBuffer(data), 'got a buffer')
327
+ t.equal(0, data.length, 'got a zero-length buffer')
328
+ t.end()
329
+ }).end()
330
+ })
331
+
332
+ tape('unicode string', function (t) {
333
+ t.plan(2)
334
+ var inp1 = '\u2600'
335
+ , inp2 = '\u2603'
336
+ , exp = inp1 + ' and ' + inp2
337
+ , bl = BufferList()
338
+ bl.write(inp1)
339
+ bl.write(' and ')
340
+ bl.write(inp2)
341
+ t.equal(exp, bl.toString())
342
+ t.equal(new Buffer(exp).toString('hex'), bl.toString('hex'))
343
+ })
344
+
345
+ tape('should emit finish', function (t) {
346
+ var source = BufferList()
347
+ , dest = BufferList()
348
+
349
+ source.write('hello')
350
+ source.pipe(dest)
351
+
352
+ dest.on('finish', function () {
353
+ t.equal(dest.toString('utf8'), 'hello')
354
+ t.end()
355
+ })
356
+ })
357
+
358
+ tape('basic copy', function (t) {
359
+ var buf = crypto.randomBytes(1024)
360
+ , buf2 = new Buffer(1024)
361
+ , b = BufferList(buf)
362
+
363
+ b.copy(buf2)
364
+ t.equal(b.slice().toString('hex'), buf2.toString('hex'), 'same buffer')
365
+ t.end()
366
+ })
367
+
368
+ tape('copy after many appends', function (t) {
369
+ var buf = crypto.randomBytes(512)
370
+ , buf2 = new Buffer(1024)
371
+ , b = BufferList(buf)
372
+
373
+ b.append(buf)
374
+ b.copy(buf2)
375
+ t.equal(b.slice().toString('hex'), buf2.toString('hex'), 'same buffer')
376
+ t.end()
377
+ })
378
+
379
+ tape('copy at a precise position', function (t) {
380
+ var buf = crypto.randomBytes(1004)
381
+ , buf2 = new Buffer(1024)
382
+ , b = BufferList(buf)
383
+
384
+ b.copy(buf2, 20)
385
+ t.equal(b.slice().toString('hex'), buf2.slice(20).toString('hex'), 'same buffer')
386
+ t.end()
387
+ })
388
+
389
+ tape('copy starting from a precise location', function (t) {
390
+ var buf = crypto.randomBytes(10)
391
+ , buf2 = new Buffer(5)
392
+ , b = BufferList(buf)
393
+
394
+ b.copy(buf2, 0, 5)
395
+ t.equal(b.slice(5).toString('hex'), buf2.toString('hex'), 'same buffer')
396
+ t.end()
397
+ })
398
+
399
+ tape('copy in an interval', function (t) {
400
+ var buf = crypto.randomBytes(10)
401
+ , buf2 = new Buffer(3)
402
+ , b = BufferList(buf)
403
+ , expected = new Buffer(3)
404
+
405
+ // put the same old data there
406
+ buf2.copy(expected)
407
+ buf.copy(expected, 0, 5, 7)
408
+
409
+ b.copy(buf2, 0, 5, 7)
410
+ t.equal(expected.slice().toString('hex'), buf2.toString('hex'), 'same buffer')
411
+ t.end()
412
+ })
413
+
414
+ tape('copy an interval between two buffers', function (t) {
415
+ var buf = crypto.randomBytes(10)
416
+ , buf2 = new Buffer(10)
417
+ , b = BufferList(buf)
418
+
419
+ b.append(buf)
420
+ b.copy(buf2, 0, 5, 15)
421
+
422
+ t.equal(b.slice(5, 15).toString('hex'), buf2.toString('hex'), 'same buffer')
423
+ t.end()
424
+ })
425
+
426
+ tape('duplicate', function (t) {
427
+ t.plan(2)
428
+
429
+ var bl = new BufferList('abcdefghij\xff\x00')
430
+ , dup = bl.duplicate()
431
+
432
+ t.equal(bl.prototype, dup.prototype)
433
+ t.equal(bl.toString('hex'), dup.toString('hex'))
434
+ })
435
+
436
+ !process.browser && tape('handle error', function (t) {
437
+ t.plan(2)
438
+ fs.createReadStream('/does/not/exist').pipe(BufferList(function (err, data) {
439
+ t.ok(err instanceof Error, 'has error')
440
+ t.notOk(data, 'no data')
441
+ }))
442
+ })
package/test/sauce.js ADDED
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env node
2
+
3
+ const user = process.env.SAUCE_USER
4
+ , key = process.env.SAUCE_KEY
5
+ , path = require('path')
6
+ , brtapsauce = require('brtapsauce')
7
+ , testFile = path.join(__dirname, 'basic-test.js')
8
+
9
+ , capabilities = [
10
+ { browserName: 'chrome' , platform: 'Windows XP', version: '' }
11
+ , { browserName: 'firefox' , platform: 'Windows 8' , version: '' }
12
+ , { browserName: 'firefox' , platform: 'Windows XP', version: '4' }
13
+ , { browserName: 'internet explorer' , platform: 'Windows 8' , version: '10' }
14
+ , { browserName: 'internet explorer' , platform: 'Windows 7' , version: '9' }
15
+ , { browserName: 'internet explorer' , platform: 'Windows 7' , version: '8' }
16
+ , { browserName: 'internet explorer' , platform: 'Windows XP', version: '7' }
17
+ , { browserName: 'internet explorer' , platform: 'Windows XP', version: '6' }
18
+ , { browserName: 'safari' , platform: 'Windows 7' , version: '5' }
19
+ , { browserName: 'safari' , platform: 'OS X 10.8' , version: '6' }
20
+ , { browserName: 'opera' , platform: 'Windows 7' , version: '' }
21
+ , { browserName: 'opera' , platform: 'Windows 7' , version: '11' }
22
+ , { browserName: 'ipad' , platform: 'OS X 10.8' , version: '6' }
23
+ , { browserName: 'android' , platform: 'Linux' , version: '4.0', 'device-type': 'tablet' }
24
+ ]
25
+
26
+ if (!user)
27
+ throw new Error('Must set a SAUCE_USER env var')
28
+ if (!key)
29
+ throw new Error('Must set a SAUCE_KEY env var')
30
+
31
+ brtapsauce({
32
+ name : 'Traversty'
33
+ , user : user
34
+ , key : key
35
+ , brsrc : testFile
36
+ , capabilities : capabilities
37
+ , options : { timeout: 60 * 6 }
38
+ })
package/test/test.js ADDED
@@ -0,0 +1,9 @@
1
+ require('./basic-test')
2
+
3
+ if (!process.env.SAUCE_KEY || !process.env.SAUCE_USER)
4
+ return console.log('SAUCE_KEY and/or SAUCE_USER not set, not running sauce tests')
5
+
6
+ if (!/v0\.10/.test(process.version))
7
+ return console.log('Not Node v0.10.x, not running sauce tests')
8
+
9
+ require('./sauce.js')