Skip to content

Commit 746d487

Browse files
tim-smartry
authored andcommitted
FastBuffer implementation. API needs migration
1 parent ef54777 commit 746d487

3 files changed

Lines changed: 179 additions & 2 deletions

File tree

lib/buffer.js

Lines changed: 163 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
var Buffer = process.binding('buffer').Buffer;
22

3-
exports.Buffer = Buffer;
4-
53
function toHex (n) {
64
if (n < 16) return "0" + n.toString(16);
75
return n.toString(16);
@@ -87,3 +85,166 @@ Buffer.prototype.get = function (index) {
8785
Buffer.prototype.set = function (index, value) {
8886
return this[index] = value;
8987
};
88+
89+
// FastBuffer
90+
var POOLSIZE = 8*1024;
91+
var pool;
92+
93+
function allocPool () {
94+
pool = new Buffer(POOLSIZE);
95+
pool.used = 0;
96+
}
97+
98+
function FastBuffer (subject, encoding, legacy, slice_legacy) {
99+
var length, type;
100+
101+
// Are we slicing?
102+
if (typeof legacy === 'number') {
103+
this.parent = subject;
104+
this.length = encoding;
105+
this.offset = legacy;
106+
legacy = slice_legacy;
107+
} else {
108+
// Find the length
109+
switch (type = typeof subject) {
110+
case 'number':
111+
length = subject;
112+
break;
113+
114+
case 'string':
115+
case 'object': // Assume object is an array
116+
length = subject.length;
117+
break;
118+
119+
default:
120+
throw new Error("First argument need to be an number, array or string.");
121+
}
122+
123+
this.length = length;
124+
125+
if (length > POOLSIZE) {
126+
// Big buffer, just alloc one.
127+
this.parent = new Buffer(subject, encoding);
128+
this.offset = 0;
129+
} else {
130+
// Small buffer.
131+
if (!pool || pool.length - pool.used < length) allocPool();
132+
this.parent = pool;
133+
this.offset = pool.used;
134+
pool.used += length;
135+
136+
// Do we need to write stuff?
137+
if (type !== 'number') {
138+
// Assume object is an array
139+
if (type === 'object') {
140+
for (var i = 0; i < length; i++) {
141+
this.parent[i + this.offset] = subject[i];
142+
}
143+
} else {
144+
// We are a string
145+
this.write(subject, 0, encoding);
146+
}
147+
}
148+
}
149+
}
150+
151+
// Make sure the api is equivilent to old buffers, unless user doesn't
152+
// want overhead
153+
if (legacy !== false) {
154+
Buffer.makeFastBuffer(this.parent, this, this.offset, this.length);
155+
}
156+
}
157+
158+
exports.FastBuffer = FastBuffer;
159+
exports.Buffer = FastBuffer;
160+
161+
// Static methods
162+
FastBuffer.isBuffer = function isBuffer(b) {
163+
return b instanceof FastBuffer;
164+
};
165+
166+
// Inspect
167+
FastBuffer.prototype.inspect = function inspect() {
168+
var out = [],
169+
len = this.length;
170+
for (var i = 0; i < len; i++) {
171+
out[i] = toHex(this.parent[i + this.offset]);
172+
}
173+
return "<Buffer " + out.join(" ") + ">";
174+
};
175+
176+
FastBuffer.prototype.get = function (i) {
177+
if (i < 0 || i >= this.length) throw new Error("oob");
178+
return this.parent[this.offset + i];
179+
};
180+
181+
FastBuffer.prototype.set = function (i, v) {
182+
if (i < 0 || i >= this.length) throw new Error("oob");
183+
return this.parent[this.offset + i] = v;
184+
};
185+
186+
// TODO define slice, toString, write, etc.
187+
// slice should not use c++
188+
189+
// write(string, offset = 0, encoding = 'uft8')
190+
FastBuffer.prototype.write = function write (string, offset, encoding) {
191+
if (!isFinite(offset)) {
192+
var swap = encoding;
193+
encoding = offset;
194+
offset = swap;
195+
}
196+
197+
var max_length;
198+
offset || (offset = 0);
199+
encoding || (encoding = 'uft8');
200+
201+
// Make sure we are not going to overflow
202+
max_length = this.length - offset;
203+
if (string.length > max_length) {
204+
string = string.slice(0, max_length);
205+
}
206+
207+
return this.parent.write(string, this.offset + offset, encoding);
208+
}
209+
210+
// toString(encoding, start=0, end=buffer.length)
211+
FastBuffer.prototype.toString = function toSting (encoding, start, end) {
212+
encoding || (encoding = 'utf8');
213+
start || (start = 0);
214+
end || (end = this.length);
215+
216+
// Make sure we aren't oob
217+
if (end > this.length) {
218+
end = this.length;
219+
}
220+
221+
return this.parent.toString(encoding, start + this.offset, end + this.offset);
222+
};
223+
224+
// byteLength
225+
FastBuffer.byteLength = Buffer.byteLength;
226+
227+
// copy(targetBuffer, targetStart, sourceStart, sourceEnd=buffer.length)
228+
FastBuffer.prototype.copy = function copy (target_buffer, target_start, start, end) {
229+
start || (start = 0);
230+
end || (end = this.length);
231+
232+
// Are we oob?
233+
if (end > this.length) {
234+
end = this.length;
235+
}
236+
237+
return this.parent.copy(target_buffer, target_start, start + this.offset, end + this.offset);
238+
};
239+
240+
// slice(start, end)
241+
FastBuffer.prototype.slice = function slice (start, end, legacy) {
242+
if (end > this.length) {
243+
throw new Error("oob");
244+
}
245+
if (start > end) {
246+
throw new Error("oob");
247+
}
248+
249+
return new FastBuffer(this.parent, end - start, +start + this.offset, legacy);
250+
};

src/node_buffer.cc

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,21 @@ Buffer::~Buffer() {
264264
}
265265

266266

267+
Handle<Value> Buffer::MakeFastBuffer(const Arguments &args) {
268+
HandleScope scope;
269+
270+
Buffer *buffer = ObjectWrap::Unwrap<Buffer>(args[0]->ToObject());
271+
Local<Object> fast_buffer = args[1]->ToObject();;
272+
uint32_t offset = args[2]->Uint32Value();
273+
uint32_t length = args[3]->Uint32Value();
274+
275+
fast_buffer->SetIndexedPropertiesToPixelData((uint8_t*)buffer->data() + offset,
276+
length);
277+
278+
return Undefined();
279+
}
280+
281+
267282
char* Buffer::data() {
268283
return blob_->data + off_;
269284
}

src/node_buffer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ class Buffer : public ObjectWrap {
5151
static v8::Persistent<v8::FunctionTemplate> constructor_template;
5252

5353
static v8::Handle<v8::Value> New(const v8::Arguments &args);
54+
static v8::Handle<v8::Value> MakeFastBuffer(const v8::Arguments &args);
5455
static v8::Handle<v8::Value> Slice(const v8::Arguments &args);
5556
static v8::Handle<v8::Value> BinarySlice(const v8::Arguments &args);
5657
static v8::Handle<v8::Value> AsciiSlice(const v8::Arguments &args);

0 commit comments

Comments
 (0)