mirror of https://github.com/lukechilds/node.git
Browse Source
Can now call fill() using following parameters if value is a String: fill(string[, start[, end]][, encoding]) And with the following if value is a Buffer: fill(buffer[, start[, end]]) The encoding is ignored if value is not a String. All other non-Buffer values are coerced to a uint32. A multibyte strings will simply be copied into the Buffer until the number of bytes run out. Meaning partial strings can be left behind: Buffer(3).fill('\u0222'); // returns: <Buffer c8 a2 c8> In some encoding cases, such as 'hex', fill() will throw if the input string is not valid. PR-URL: https://github.com/nodejs/node/pull/4935 Reviewed-By: James M Snell <jasnell@gmail.com>process-exit-stdio-flushing
Trevor Norris
9 years ago
6 changed files with 411 additions and 32 deletions
@ -0,0 +1,241 @@ |
|||
'use strict'; |
|||
|
|||
require('../common'); |
|||
const assert = require('assert'); |
|||
const os = require('os'); |
|||
const SIZE = 28; |
|||
|
|||
const buf1 = Buffer(SIZE); |
|||
const buf2 = Buffer(SIZE); |
|||
|
|||
|
|||
// Default encoding
|
|||
testBufs('abc'); |
|||
testBufs('\u0222aa'); |
|||
testBufs('a\u0234b\u0235c\u0236'); |
|||
testBufs('abc', 4); |
|||
testBufs('abc', 5); |
|||
testBufs('abc', SIZE); |
|||
testBufs('\u0222aa', 2); |
|||
testBufs('\u0222aa', 8); |
|||
testBufs('a\u0234b\u0235c\u0236', 4); |
|||
testBufs('a\u0234b\u0235c\u0236', 12); |
|||
testBufs('abc', 4, -1); |
|||
testBufs('abc', 4, 1); |
|||
testBufs('abc', 5, 1); |
|||
testBufs('\u0222aa', 2, -1); |
|||
testBufs('\u0222aa', 8, 1); |
|||
testBufs('a\u0234b\u0235c\u0236', 4, -1); |
|||
testBufs('a\u0234b\u0235c\u0236', 4, 1); |
|||
testBufs('a\u0234b\u0235c\u0236', 12, 1); |
|||
|
|||
|
|||
// UTF8
|
|||
testBufs('abc', 'utf8'); |
|||
testBufs('\u0222aa', 'utf8'); |
|||
testBufs('a\u0234b\u0235c\u0236', 'utf8'); |
|||
testBufs('abc', 4, 'utf8'); |
|||
testBufs('abc', 5, 'utf8'); |
|||
testBufs('abc', SIZE, 'utf8'); |
|||
testBufs('\u0222aa', 2, 'utf8'); |
|||
testBufs('\u0222aa', 8, 'utf8'); |
|||
testBufs('a\u0234b\u0235c\u0236', 4, 'utf8'); |
|||
testBufs('a\u0234b\u0235c\u0236', 12, 'utf8'); |
|||
testBufs('abc', 4, -1, 'utf8'); |
|||
testBufs('abc', 4, 1, 'utf8'); |
|||
testBufs('abc', 5, 1, 'utf8'); |
|||
testBufs('\u0222aa', 2, -1, 'utf8'); |
|||
testBufs('\u0222aa', 8, 1, 'utf8'); |
|||
testBufs('a\u0234b\u0235c\u0236', 4, -1, 'utf8'); |
|||
testBufs('a\u0234b\u0235c\u0236', 4, 1, 'utf8'); |
|||
testBufs('a\u0234b\u0235c\u0236', 12, 1, 'utf8'); |
|||
assert.equal(Buffer(1).fill(0).fill('\u0222')[0], 0xc8); |
|||
|
|||
|
|||
// BINARY
|
|||
testBufs('abc', 'binary'); |
|||
testBufs('\u0222aa', 'binary'); |
|||
testBufs('a\u0234b\u0235c\u0236', 'binary'); |
|||
testBufs('abc', 4, 'binary'); |
|||
testBufs('abc', 5, 'binary'); |
|||
testBufs('abc', SIZE, 'binary'); |
|||
testBufs('\u0222aa', 2, 'binary'); |
|||
testBufs('\u0222aa', 8, 'binary'); |
|||
testBufs('a\u0234b\u0235c\u0236', 4, 'binary'); |
|||
testBufs('a\u0234b\u0235c\u0236', 12, 'binary'); |
|||
testBufs('abc', 4, -1, 'binary'); |
|||
testBufs('abc', 4, 1, 'binary'); |
|||
testBufs('abc', 5, 1, 'binary'); |
|||
testBufs('\u0222aa', 2, -1, 'binary'); |
|||
testBufs('\u0222aa', 8, 1, 'binary'); |
|||
testBufs('a\u0234b\u0235c\u0236', 4, -1, 'binary'); |
|||
testBufs('a\u0234b\u0235c\u0236', 4, 1, 'binary'); |
|||
testBufs('a\u0234b\u0235c\u0236', 12, 1, 'binary'); |
|||
|
|||
|
|||
// UCS2
|
|||
testBufs('abc', 'ucs2'); |
|||
testBufs('\u0222aa', 'ucs2'); |
|||
testBufs('a\u0234b\u0235c\u0236', 'ucs2'); |
|||
testBufs('abc', 4, 'ucs2'); |
|||
testBufs('abc', SIZE, 'ucs2'); |
|||
testBufs('\u0222aa', 2, 'ucs2'); |
|||
testBufs('\u0222aa', 8, 'ucs2'); |
|||
testBufs('a\u0234b\u0235c\u0236', 4, 'ucs2'); |
|||
testBufs('a\u0234b\u0235c\u0236', 12, 'ucs2'); |
|||
testBufs('abc', 4, -1, 'ucs2'); |
|||
testBufs('abc', 4, 1, 'ucs2'); |
|||
testBufs('abc', 5, 1, 'ucs2'); |
|||
testBufs('\u0222aa', 2, -1, 'ucs2'); |
|||
testBufs('\u0222aa', 8, 1, 'ucs2'); |
|||
testBufs('a\u0234b\u0235c\u0236', 4, -1, 'ucs2'); |
|||
testBufs('a\u0234b\u0235c\u0236', 4, 1, 'ucs2'); |
|||
testBufs('a\u0234b\u0235c\u0236', 12, 1, 'ucs2'); |
|||
assert.equal(Buffer(1).fill('\u0222', 'ucs2')[0], |
|||
os.endianness() === 'LE' ? 0x22 : 0x02); |
|||
|
|||
|
|||
// HEX
|
|||
testBufs('616263', 'hex'); |
|||
testBufs('c8a26161', 'hex'); |
|||
testBufs('61c8b462c8b563c8b6', 'hex'); |
|||
testBufs('616263', 4, 'hex'); |
|||
testBufs('616263', 5, 'hex'); |
|||
testBufs('616263', SIZE, 'hex'); |
|||
testBufs('c8a26161', 2, 'hex'); |
|||
testBufs('c8a26161', 8, 'hex'); |
|||
testBufs('61c8b462c8b563c8b6', 4, 'hex'); |
|||
testBufs('61c8b462c8b563c8b6', 12, 'hex'); |
|||
testBufs('616263', 4, -1, 'hex'); |
|||
testBufs('616263', 4, 1, 'hex'); |
|||
testBufs('616263', 5, 1, 'hex'); |
|||
testBufs('c8a26161', 2, -1, 'hex'); |
|||
testBufs('c8a26161', 8, 1, 'hex'); |
|||
testBufs('61c8b462c8b563c8b6', 4, -1, 'hex'); |
|||
testBufs('61c8b462c8b563c8b6', 4, 1, 'hex'); |
|||
testBufs('61c8b462c8b563c8b6', 12, 1, 'hex'); |
|||
// Make sure this operation doesn't go on forever
|
|||
buf1.fill('yKJh', 'hex'); |
|||
assert.throws(() => buf1.fill('\u0222', 'hex')); |
|||
|
|||
|
|||
// BASE64
|
|||
testBufs('YWJj', 'ucs2'); |
|||
testBufs('yKJhYQ==', 'ucs2'); |
|||
testBufs('Yci0Ysi1Y8i2', 'ucs2'); |
|||
testBufs('YWJj', 4, 'ucs2'); |
|||
testBufs('YWJj', SIZE, 'ucs2'); |
|||
testBufs('yKJhYQ==', 2, 'ucs2'); |
|||
testBufs('yKJhYQ==', 8, 'ucs2'); |
|||
testBufs('Yci0Ysi1Y8i2', 4, 'ucs2'); |
|||
testBufs('Yci0Ysi1Y8i2', 12, 'ucs2'); |
|||
testBufs('YWJj', 4, -1, 'ucs2'); |
|||
testBufs('YWJj', 4, 1, 'ucs2'); |
|||
testBufs('YWJj', 5, 1, 'ucs2'); |
|||
testBufs('yKJhYQ==', 2, -1, 'ucs2'); |
|||
testBufs('yKJhYQ==', 8, 1, 'ucs2'); |
|||
testBufs('Yci0Ysi1Y8i2', 4, -1, 'ucs2'); |
|||
testBufs('Yci0Ysi1Y8i2', 4, 1, 'ucs2'); |
|||
testBufs('Yci0Ysi1Y8i2', 12, 1, 'ucs2'); |
|||
|
|||
|
|||
// Buffer
|
|||
const buf2Fill = Buffer(1).fill(2); |
|||
assert.deepEqual(genBuffer(4, [buf2Fill]), [2, 2, 2, 2]); |
|||
assert.deepEqual(genBuffer(4, [buf2Fill, 1]), [0, 2, 2, 2]); |
|||
assert.deepEqual(genBuffer(4, [buf2Fill, 1, 3]), [0, 2, 2, 0]); |
|||
assert.deepEqual(genBuffer(4, [buf2Fill, 1, 1]), [0, 0, 0, 0]); |
|||
assert.deepEqual(genBuffer(4, [buf2Fill, 1, -1]), [0, 0, 0, 0]); |
|||
const hexBufFill = Buffer(2).fill(0).fill('0102', 'hex'); |
|||
assert.deepEqual(genBuffer(4, [hexBufFill]), [1, 2, 1, 2]); |
|||
assert.deepEqual(genBuffer(4, [hexBufFill, 1]), [0, 1, 2, 1]); |
|||
assert.deepEqual(genBuffer(4, [hexBufFill, 1, 3]), [0, 1, 2, 0]); |
|||
assert.deepEqual(genBuffer(4, [hexBufFill, 1, 1]), [0, 0, 0, 0]); |
|||
assert.deepEqual(genBuffer(4, [hexBufFill, 1, -1]), [0, 0, 0, 0]); |
|||
|
|||
|
|||
// Check exceptions
|
|||
assert.throws(() => buf1.fill(0, -1)); |
|||
assert.throws(() => buf1.fill(0, 0, buf1.length + 1)); |
|||
assert.throws(() => buf1.fill('', -1)); |
|||
assert.throws(() => buf1.fill('', 0, buf1.length + 1)); |
|||
assert.throws(() => buf1.fill('a', 0, buf1.length, 'node rocks!')); |
|||
assert.throws(() => buf1.fill('a', 0, 0, NaN)); |
|||
assert.throws(() => buf1.fill('a', 0, 0, null)); |
|||
assert.throws(() => buf1.fill('a', 0, 0, 'foo')); |
|||
|
|||
|
|||
function genBuffer(size, args) { |
|||
const b = Buffer(size); |
|||
return b.fill(0).fill.apply(b, args); |
|||
} |
|||
|
|||
|
|||
function bufReset() { |
|||
buf1.fill(0); |
|||
buf2.fill(0); |
|||
} |
|||
|
|||
|
|||
// This is mostly accurate. Except write() won't write partial bytes to the
|
|||
// string while fill() blindly copies bytes into memory. To account for that an
|
|||
// error will be thrown if not all the data can be written, and the SIZE has
|
|||
// been massaged to work with the input characters.
|
|||
function writeToFill(string, offset, end, encoding) { |
|||
if (typeof offset === 'string') { |
|||
encoding = offset; |
|||
offset = 0; |
|||
end = buf2.length; |
|||
} else if (typeof end === 'string') { |
|||
encoding = end; |
|||
end = buf2.length; |
|||
} else if (end === undefined) { |
|||
end = buf2.length; |
|||
} |
|||
|
|||
if (offset < 0 || end > buf2.length) |
|||
throw new RangeError('Out of range index'); |
|||
|
|||
if (end <= offset) |
|||
return buf2; |
|||
|
|||
offset >>>= 0; |
|||
end >>>= 0; |
|||
assert(offset <= buf2.length); |
|||
|
|||
// Convert "end" to "length" (which write understands).
|
|||
const length = end - offset < 0 ? 0 : end - offset; |
|||
|
|||
var wasZero = false; |
|||
do { |
|||
const written = buf2.write(string, offset, length, encoding); |
|||
offset += written; |
|||
// Safety check in case write falls into infinite loop.
|
|||
if (written === 0) { |
|||
if (wasZero) |
|||
throw new Error('Could not write all data to Buffer'); |
|||
else |
|||
wasZero = true; |
|||
} |
|||
} while (offset < buf2.length); |
|||
|
|||
// Correction for UCS2 operations.
|
|||
if (os.endianness() === 'BE' && encoding === 'ucs2') { |
|||
for (var i = 0; i < buf2.length; i += 2) { |
|||
var tmp = buf2[i]; |
|||
buf2[i] = buf2[i + 1]; |
|||
buf2[i + 1] = tmp; |
|||
} |
|||
} |
|||
|
|||
return buf2; |
|||
} |
|||
|
|||
|
|||
function testBufs(string, offset, length, encoding) { |
|||
bufReset(); |
|||
buf1.fill.apply(buf1, arguments); |
|||
// Swap bytes on BE archs for ucs2 encoding.
|
|||
assert.deepStrictEqual(buf1.fill.apply(buf1, arguments), |
|||
writeToFill.apply(null, arguments)); |
|||
} |
Loading…
Reference in new issue