Skip to content

Commit 50e147b

Browse files
committed
Add an optional length argument to Buffer.write()
Fixes #243. Fixes #1361.
1 parent fa829b0 commit 50e147b

File tree

3 files changed

+122
-33
lines changed

3 files changed

+122
-33
lines changed

doc/api/buffers.markdown

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,12 @@ Allocates a new buffer using an `array` of octets.
4747

4848
Allocates a new buffer containing the given `str`.
4949

50-
### buffer.write(string, offset=0, encoding='utf8')
50+
### buffer.write(string, offset=0, length=buffer.length-offset, encoding='utf8')
5151

52-
Writes `string` to the buffer at `offset` using the given encoding. Returns
53-
number of octets written. If `buffer` did not contain enough space to fit
54-
the entire string, it will write a partial amount of the string.
55-
The method will not write partial characters.
52+
Writes `string` to the buffer at `offset` using the given encoding. `length` is
53+
the number of bytes to write. Returns number of octets written. If `buffer` did
54+
not contain enough space to fit the entire string, it will write a partial
55+
amount of the string. The method will not write partial characters.
5656

5757
Example: write a utf8 string into a buffer, then print it
5858

lib/buffer.js

Lines changed: 70 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -92,15 +92,27 @@ SlowBuffer.prototype.toString = function(encoding, start, end) {
9292
};
9393

9494

95-
SlowBuffer.prototype.hexWrite = function(string, offset) {
96-
var len = string.length;
95+
SlowBuffer.prototype.hexWrite = function(string, offset, length) {
9796
offset = +offset || 0;
97+
var remaining = this.length - offset;
98+
if (!length) {
99+
length = remaining;
100+
} else {
101+
length = +length;
102+
if (length > remaining) {
103+
length = remaining;
104+
}
105+
}
98106

99107
// must be an even number of digits
100-
if (len % 2) {
108+
var strLen = string.length;
109+
if (strLen % 2) {
101110
throw new Error('Invalid hex string');
102111
}
103-
for (var i = 0; i < len / 2; i++) {
112+
if (length > strLen / 2) {
113+
length = strLen / 2;
114+
}
115+
for (var i = 0; i < length; i++) {
104116
var byte = parseInt(string.substr(i * 2, 2), 16);
105117
if (isNaN(byte)) throw new Error('Invalid hex string');
106118
this[offset + i] = byte;
@@ -109,38 +121,53 @@ SlowBuffer.prototype.hexWrite = function(string, offset) {
109121
};
110122

111123

112-
SlowBuffer.prototype.write = function(string, offset, encoding) {
113-
// Support both (string, offset, encoding)
114-
// and the legacy (string, encoding, offset)
115-
if (!isFinite(offset)) {
124+
SlowBuffer.prototype.write = function(string, offset, length, encoding) {
125+
// Support both (string, offset, length, encoding)
126+
// and the legacy (string, encoding, offset, length)
127+
if (isFinite(offset)) {
128+
if (!isFinite(length)) {
129+
encoding = length;
130+
length = undefined;
131+
}
132+
} else { // legacy
116133
var swap = encoding;
117134
encoding = offset;
118-
offset = swap;
135+
offset = length;
136+
length = swap;
119137
}
120138

121139
offset = +offset || 0;
140+
var remaining = this.length - offset;
141+
if (!length) {
142+
length = remaining;
143+
} else {
144+
length = +length;
145+
if (length > remaining) {
146+
length = remaining;
147+
}
148+
}
122149
encoding = String(encoding || 'utf8').toLowerCase();
123150

124151
switch (encoding) {
125152
case 'hex':
126-
return this.hexWrite(string, offset);
153+
return this.hexWrite(string, offset, length);
127154

128155
case 'utf8':
129156
case 'utf-8':
130-
return this.utf8Write(string, offset);
157+
return this.utf8Write(string, offset, length);
131158

132159
case 'ascii':
133-
return this.asciiWrite(string, offset);
160+
return this.asciiWrite(string, offset, length);
134161

135162
case 'binary':
136-
return this.binaryWrite(string, offset);
163+
return this.binaryWrite(string, offset, length);
137164

138165
case 'base64':
139-
return this.base64Write(string, offset);
166+
return this.base64Write(string, offset, length);
140167

141168
case 'ucs2':
142169
case 'ucs-2':
143-
return this.ucs2Write(string, offset);
170+
return this.ucs2Write(string, offset, length);
144171

145172
default:
146173
throw new Error('Unknown encoding');
@@ -271,47 +298,61 @@ Buffer.prototype.set = function set(i, v) {
271298
};
272299

273300

274-
// write(string, offset = 0, encoding = 'utf8')
275-
Buffer.prototype.write = function(string, offset, encoding) {
276-
if (!isFinite(offset)) {
301+
// write(string, offset = 0, length = buffer.length-offset, encoding = 'utf8')
302+
Buffer.prototype.write = function(string, offset, length, encoding) {
303+
// Support both (string, offset, length, encoding)
304+
// and the legacy (string, encoding, offset, length)
305+
if (isFinite(offset)) {
306+
if (!isFinite(length)) {
307+
encoding = length;
308+
length = undefined;
309+
}
310+
} else { // legacy
277311
var swap = encoding;
278312
encoding = offset;
279-
offset = swap;
313+
offset = length;
314+
length = swap;
280315
}
281316

282317
offset = +offset || 0;
318+
var remaining = this.length - offset;
319+
if (!length) {
320+
length = remaining;
321+
} else {
322+
length = +length;
323+
if (length > remaining) {
324+
length = remaining;
325+
}
326+
}
283327
encoding = String(encoding || 'utf8').toLowerCase();
284328

285-
// Make sure we are not going to overflow
286-
var maxLength = this.length - offset;
287-
288329
var ret;
289330
switch (encoding) {
290331
case 'hex':
291-
ret = this.parent.hexWrite(string, this.offset + offset, maxLength);
332+
ret = this.parent.hexWrite(string, this.offset + offset, length);
292333
break;
293334

294335
case 'utf8':
295336
case 'utf-8':
296-
ret = this.parent.utf8Write(string, this.offset + offset, maxLength);
337+
ret = this.parent.utf8Write(string, this.offset + offset, length);
297338
break;
298339

299340
case 'ascii':
300-
ret = this.parent.asciiWrite(string, this.offset + offset, maxLength);
341+
ret = this.parent.asciiWrite(string, this.offset + offset, length);
301342
break;
302343

303344
case 'binary':
304-
ret = this.parent.binaryWrite(string, this.offset + offset, maxLength);
345+
ret = this.parent.binaryWrite(string, this.offset + offset, length);
305346
break;
306347

307348
case 'base64':
308349
// Warning: maxLength not taken into account in base64Write
309-
ret = this.parent.base64Write(string, this.offset + offset, maxLength);
350+
ret = this.parent.base64Write(string, this.offset + offset, length);
310351
break;
311352

312353
case 'ucs2':
313354
case 'ucs-2':
314-
ret = this.parent.ucs2Write(string, this.offset + offset, maxLength);
355+
ret = this.parent.ucs2Write(string, this.offset + offset, length);
315356
break;
316357

317358
default:
@@ -1019,3 +1060,4 @@ Buffer.prototype.writeDouble = function(value, offset, endian) {
10191060
verifIEEE754(value, 1.7976931348623157E+308, -1.7976931348623157E+308);
10201061
IEEE754.writeIEEE754(buffer, value, offset, endian, 52, 8);
10211062
};
1063+

test/simple/test-buffer.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,3 +621,50 @@ assert.equal(written, 9);
621621
written = buf.write('あいう\0'); // 3bytes * 3 + 1byte
622622
assert.equal(written, 10);
623623

624+
// #243 Test write() with maxLength
625+
var buf = new Buffer(4);
626+
buf.fill(0xFF);
627+
var written = buf.write('abcd', 1, 2, 'utf8');
628+
console.log(buf);
629+
assert.equal(written, 2);
630+
assert.equal(buf[0], 0xFF);
631+
assert.equal(buf[1], 0x61);
632+
assert.equal(buf[2], 0x62);
633+
assert.equal(buf[3], 0xFF);
634+
635+
buf.fill(0xFF);
636+
written = buf.write('abcd', 1, 4);
637+
console.log(buf);
638+
assert.equal(written, 3);
639+
assert.equal(buf[0], 0xFF);
640+
assert.equal(buf[1], 0x61);
641+
assert.equal(buf[2], 0x62);
642+
assert.equal(buf[3], 0x63);
643+
644+
buf.fill(0xFF);
645+
written = buf.write('abcd', 'utf8', 1, 2); // legacy style
646+
console.log(buf);
647+
assert.equal(written, 2);
648+
assert.equal(buf[0], 0xFF);
649+
assert.equal(buf[1], 0x61);
650+
assert.equal(buf[2], 0x62);
651+
assert.equal(buf[3], 0xFF);
652+
653+
buf.fill(0xFF);
654+
written = buf.write('abcdef', 1, 2, 'hex');
655+
console.log(buf);
656+
assert.equal(written, 2);
657+
assert.equal(buf[0], 0xFF);
658+
assert.equal(buf[1], 0xAB);
659+
assert.equal(buf[2], 0xCD);
660+
assert.equal(buf[3], 0xFF);
661+
662+
buf.fill(0xFF);
663+
written = buf.write('abcd', 0, 2, 'ucs2');
664+
console.log(buf);
665+
assert.equal(written, 2);
666+
assert.equal(buf[0], 0x61);
667+
assert.equal(buf[1], 0x00);
668+
assert.equal(buf[2], 0xFF);
669+
assert.equal(buf[3], 0xFF);
670+

0 commit comments

Comments
 (0)