diff --git a/src/colony/lua/colony-node.lua b/src/colony/lua/colony-node.lua index 72a0d582..40db05aa 100644 --- a/src/colony/lua/colony-node.lua +++ b/src/colony/lua/colony-node.lua @@ -209,6 +209,7 @@ end local buffer_proto = js_obj({ fill = function (this, value, offset, endoffset) + checkCopyOnWrite(this); local sourceBuffer = getmetatable(this).buffer local sourceBufferLength = getmetatable(this).bufferlen offset = tonumber(offset) @@ -224,6 +225,8 @@ local buffer_proto = js_obj({ slice = function (this, sourceStart, len) sourceStart = tonumber(sourceStart or 0) or 0 + checkCopyOnWrite(this); + if len == nil then len = this.length end @@ -238,11 +241,14 @@ local buffer_proto = js_obj({ local sourceBuffer = getmetatable(this).buffer local sourceBufferLength = getmetatable(this).bufferlen - return _of_buffer({}, tm.buffer_index(sourceBuffer, sourceStart), len - sourceStart) + return _of_buffer({}, tm.buffer_index(sourceBuffer, sourceStart), len - sourceStart, true) end, copy = function (this, target, targetStart, sourceStart, sourceEnd) local sourceBuffer = getmetatable(this).buffer local sourceBufferLength = getmetatable(this).bufferlen + + checkCopyOnWrite(target); + local targetBuffer = getmetatable(target).buffer local targetBufferLength = getmetatable(target).bufferlen if not sourceBuffer or not targetBuffer then @@ -359,6 +365,8 @@ buffer_proto.readDoubleLE = function (this, pos, opts) return read_buf(this, pos buffer_proto.readDoubleBE = function (this, pos, opts) return read_buf(this, pos, opts, 8, tm.buffer_read_double, 0); end function write_buf (this, value, pos, no_assert, size, fn, le) + checkCopyOnWrite(this); + local sourceBuffer = getmetatable(this).buffer local sourceBufferLength = getmetatable(this).bufferlen pos = tonumber(pos) @@ -395,7 +403,8 @@ buffer_proto.writeDoubleLE = function (this, value, pos, opts) return write_buf( buffer_proto.writeDoubleBE = function (this, value, pos, opts) return write_buf(this, value, pos, opts, 8, tm.buffer_write_double, 0); end -function _of_buffer (this, buf, length) +function _of_buffer (this, buf, length, copyOnWrite) + this._copyOnWrite = copyOnWrite; setmetatable(this, { buffer = buf, bufferlen = length, @@ -446,6 +455,17 @@ function _of_buffer (this, buf, length) return this end +function checkCopyOnWrite (this) + if this._copyOnWrite then + this._oldBuffer = getmetatable(this).buffer; + local bufCopy = tm.buffer_create(getmetatable(this).bufferlen) + tm.buffer_copy(getmetatable(this).buffer, bufCopy, 0, 0, getmetatable(this).bufferlen) + getmetatable(this).buffer = bufCopy; + this._copyOnWrite = false + this._newBuffer = getmetatable(this).buffer; + end +end + local function Buffer (this, arg, encoding) -- args local str, length = '', 0 @@ -471,7 +491,7 @@ local function Buffer (this, arg, encoding) this = {} local buf = tm.buffer_create(length) - _of_buffer(this, buf, length) + _of_buffer(this, buf, length, true) -- Lua internally uses a "binary" encoding, that is, -- operates on (1-indexable) 8-bit values. diff --git a/test/suite/buffer.js b/test/suite/buffer.js index 3769f266..ce938053 100644 --- a/test/suite/buffer.js +++ b/test/suite/buffer.js @@ -167,3 +167,27 @@ var len = buf.write('\u00bd + \u00bc = \u00be', 4); console.log('#', len + " bytes: " + buf.toString('utf8', 4, 4 + len)); ok(len == 12, 'written length is 12 byes') ok(buf.slice(4, 4 + 12).toString() == '\u00bd + \u00bc = \u00be', 'result was written') + +// copy on write -> write(type)(size) tests +var writableFunctions = ["writeUInt8", "writeUInt16LE", "writeUInt16BE", "writeUInt32LE", "writeUInt32BE", "writeInt8", + "writeInt16LE", "writeInt16BE", "writeInt32LE", "writeInt32BE", "writeFloatLE", "writeFloatBE", + "writeDoubleLE", "writeDoubleBE"]; +for (var i = 0; i other copy and slice +var buf = new Buffer(256); +buf.slice(0, 10); +console.log("old buf:", buf._oldBuffer, "new buf:", buf._newBuffer) +ok(buf._oldBuffer !== buf._newBuffer, "New buffer pointer is different than old buffer pointer"); + +var buf = new Buffer(256); +var buf2 = new Buffer(256); +buf.copy(buf2, 0, 0, buf.length); +console.log("old buf:", buf2._oldBuffer, "new buf:", buf2._newBuffer) +ok(buf2._oldBuffer !== buf2._newBuffer, "New buffer pointer is different than old buffer pointer");