Remove blobs, simplify SlowBuffer
Implement SlowBuffer.prototype.slice in js
This commit is contained in:
parent
380d12832c
commit
5bc4efe820
@ -79,6 +79,19 @@ SlowBuffer.prototype.write = function (string, offset, encoding) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// slice(start, end)
|
||||||
|
SlowBuffer.prototype.slice = function (start, end) {
|
||||||
|
if (end > this.length) {
|
||||||
|
throw new Error("oob");
|
||||||
|
}
|
||||||
|
if (start > end) {
|
||||||
|
throw new Error("oob");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Buffer(this, end - start, +start);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// Buffer
|
// Buffer
|
||||||
|
|
||||||
function Buffer (subject, encoding, offset) {
|
function Buffer (subject, encoding, offset) {
|
||||||
@ -318,4 +331,3 @@ Buffer.prototype.slice = function (start, end) {
|
|||||||
|
|
||||||
return new Buffer(this.parent, end - start, +start + this.offset);
|
return new Buffer(this.parent, end - start, +start + this.offset);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -43,49 +43,6 @@ static Persistent<String> write_sym;
|
|||||||
Persistent<FunctionTemplate> Buffer::constructor_template;
|
Persistent<FunctionTemplate> Buffer::constructor_template;
|
||||||
|
|
||||||
|
|
||||||
// Each javascript Buffer object is backed by a Blob object.
|
|
||||||
// the Blob is just a C-level chunk of bytes.
|
|
||||||
// It has a reference count.
|
|
||||||
struct Blob_ {
|
|
||||||
unsigned int refs;
|
|
||||||
size_t length;
|
|
||||||
char *data;
|
|
||||||
};
|
|
||||||
typedef struct Blob_ Blob;
|
|
||||||
|
|
||||||
|
|
||||||
static inline Blob * blob_new(size_t length) {
|
|
||||||
Blob * blob = (Blob*) malloc(sizeof(Blob));
|
|
||||||
if (!blob) return NULL;
|
|
||||||
|
|
||||||
blob->data = (char*) malloc(length);
|
|
||||||
if (!blob->data) {
|
|
||||||
free(blob);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
V8::AdjustAmountOfExternalAllocatedMemory(sizeof(Blob) + length);
|
|
||||||
blob->length = length;
|
|
||||||
blob->refs = 0;
|
|
||||||
return blob;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline void blob_ref(Blob *blob) {
|
|
||||||
blob->refs++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline void blob_unref(Blob *blob) {
|
|
||||||
assert(blob->refs > 0);
|
|
||||||
if (--blob->refs == 0) {
|
|
||||||
//fprintf(stderr, "free %d bytes\n", blob->length);
|
|
||||||
V8::AdjustAmountOfExternalAllocatedMemory(-(sizeof(Blob) + blob->length));
|
|
||||||
free(blob->data);
|
|
||||||
free(blob);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline size_t base64_decoded_size(const char *src, size_t size) {
|
static inline size_t base64_decoded_size(const char *src, size_t size) {
|
||||||
const char *const end = src + size;
|
const char *const end = src + size;
|
||||||
const int remainder = size % 4;
|
const int remainder = size % 4;
|
||||||
@ -188,22 +145,6 @@ Handle<Value> Buffer::New(const Arguments &args) {
|
|||||||
size_t length = args[0]->Uint32Value();
|
size_t length = args[0]->Uint32Value();
|
||||||
buffer = new Buffer(length);
|
buffer = new Buffer(length);
|
||||||
|
|
||||||
} else if (args[0]->IsArray()) {
|
|
||||||
Local<Array> a = Local<Array>::Cast(args[0]);
|
|
||||||
buffer = new Buffer(a->Length());
|
|
||||||
char *p = buffer->data();
|
|
||||||
for (int i = 0; i < a->Length(); i++) {
|
|
||||||
p[i] = a->Get(i)->Uint32Value();
|
|
||||||
}
|
|
||||||
} else if (args[0]->IsString()) {
|
|
||||||
buffer = new Buffer(node::ByteLength(args[0]->ToString(), ParseEncoding(args[1], UTF8)));
|
|
||||||
|
|
||||||
} else if (Buffer::HasInstance(args[0]) && args.Length() > 2) {
|
|
||||||
// var slice = new Buffer(buffer, 123, 130);
|
|
||||||
// args: parent, start, end
|
|
||||||
Buffer *parent = ObjectWrap::Unwrap<Buffer>(args[0]->ToObject());
|
|
||||||
SLICE_ARGS(args[1], args[2])
|
|
||||||
buffer = new Buffer(parent, start, end);
|
|
||||||
} else {
|
} else {
|
||||||
return ThrowException(Exception::TypeError(String::New("Bad argument")));
|
return ThrowException(Exception::TypeError(String::New("Bad argument")));
|
||||||
}
|
}
|
||||||
@ -219,40 +160,23 @@ Handle<Value> Buffer::New(const Arguments &args) {
|
|||||||
|
|
||||||
|
|
||||||
Buffer::Buffer(size_t length) : ObjectWrap() {
|
Buffer::Buffer(size_t length) : ObjectWrap() {
|
||||||
blob_ = blob_new(length);
|
|
||||||
off_ = 0;
|
off_ = 0;
|
||||||
length_ = length;
|
length_ = length;
|
||||||
|
data_ = new char[length_];
|
||||||
|
|
||||||
blob_ref(blob_);
|
V8::AdjustAmountOfExternalAllocatedMemory(sizeof(Buffer) + length_);
|
||||||
|
|
||||||
V8::AdjustAmountOfExternalAllocatedMemory(sizeof(Buffer));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Buffer::Buffer(Buffer *parent, size_t start, size_t end) : ObjectWrap() {
|
|
||||||
blob_ = parent->blob_;
|
|
||||||
assert(blob_->refs > 0);
|
|
||||||
blob_ref(blob_);
|
|
||||||
|
|
||||||
assert(start <= end);
|
|
||||||
off_ = parent->off_ + start;
|
|
||||||
length_ = end - start;
|
|
||||||
assert(length_ <= parent->length_);
|
|
||||||
|
|
||||||
V8::AdjustAmountOfExternalAllocatedMemory(sizeof(Buffer));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Buffer::~Buffer() {
|
Buffer::~Buffer() {
|
||||||
assert(blob_->refs > 0);
|
|
||||||
//fprintf(stderr, "free buffer (%d refs left)\n", blob_->refs);
|
//fprintf(stderr, "free buffer (%d refs left)\n", blob_->refs);
|
||||||
blob_unref(blob_);
|
delete data_;
|
||||||
V8::AdjustAmountOfExternalAllocatedMemory(-static_cast<long int>(sizeof(Buffer)));
|
V8::AdjustAmountOfExternalAllocatedMemory(-(sizeof(Buffer) + length_));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char* Buffer::data() {
|
char* Buffer::data() {
|
||||||
return blob_->data + off_;
|
return data_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -275,14 +199,6 @@ Handle<Value> Buffer::AsciiSlice(const Arguments &args) {
|
|||||||
Buffer *parent = ObjectWrap::Unwrap<Buffer>(args.This());
|
Buffer *parent = ObjectWrap::Unwrap<Buffer>(args.This());
|
||||||
SLICE_ARGS(args[0], args[1])
|
SLICE_ARGS(args[0], args[1])
|
||||||
|
|
||||||
#if 0
|
|
||||||
AsciiSliceExt *ext = new AsciiSliceExt(parent, start, end);
|
|
||||||
Local<String> string = String::NewExternal(ext);
|
|
||||||
// There should be at least two references to the blob now - the parent
|
|
||||||
// and the slice.
|
|
||||||
assert(parent->blob_->refs >= 2);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
char* data = parent->data() + start;
|
char* data = parent->data() + start;
|
||||||
Local<String> string = String::New(data, end - start);
|
Local<String> string = String::New(data, end - start);
|
||||||
|
|
||||||
@ -386,15 +302,6 @@ Handle<Value> Buffer::Base64Slice(const Arguments &args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Handle<Value> Buffer::Slice(const Arguments &args) {
|
|
||||||
HandleScope scope;
|
|
||||||
Local<Value> argv[3] = { args.This(), args[0], args[1] };
|
|
||||||
Local<Object> slice =
|
|
||||||
constructor_template->GetFunction()->NewInstance(3, argv);
|
|
||||||
return scope.Close(slice);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// var bytesCopied = buffer.copy(target, targetStart, sourceStart, sourceEnd);
|
// var bytesCopied = buffer.copy(target, targetStart, sourceStart, sourceEnd);
|
||||||
Handle<Value> Buffer::Copy(const Arguments &args) {
|
Handle<Value> Buffer::Copy(const Arguments &args) {
|
||||||
HandleScope scope;
|
HandleScope scope;
|
||||||
@ -443,16 +350,10 @@ Handle<Value> Buffer::Copy(const Arguments &args) {
|
|||||||
source->length() - source_start);
|
source->length() - source_start);
|
||||||
|
|
||||||
|
|
||||||
if (target->blob_ == source->blob_) {
|
|
||||||
// need to use slightly slower memmove is the ranges might overlap
|
// need to use slightly slower memmove is the ranges might overlap
|
||||||
memmove((void*)(target->data() + target_start),
|
memmove((void*)(target->data() + target_start),
|
||||||
(const void*)(source->data() + source_start),
|
(const void*)(source->data() + source_start),
|
||||||
to_copy);
|
to_copy);
|
||||||
} else {
|
|
||||||
memcpy((void*)(target->data() + target_start),
|
|
||||||
(const void*)(source->data() + source_start),
|
|
||||||
to_copy);
|
|
||||||
}
|
|
||||||
|
|
||||||
return scope.Close(Integer::New(to_copy));
|
return scope.Close(Integer::New(to_copy));
|
||||||
}
|
}
|
||||||
@ -684,7 +585,6 @@ void Buffer::Initialize(Handle<Object> target) {
|
|||||||
NODE_SET_PROTOTYPE_METHOD(constructor_template, "binarySlice", Buffer::BinarySlice);
|
NODE_SET_PROTOTYPE_METHOD(constructor_template, "binarySlice", Buffer::BinarySlice);
|
||||||
NODE_SET_PROTOTYPE_METHOD(constructor_template, "asciiSlice", Buffer::AsciiSlice);
|
NODE_SET_PROTOTYPE_METHOD(constructor_template, "asciiSlice", Buffer::AsciiSlice);
|
||||||
NODE_SET_PROTOTYPE_METHOD(constructor_template, "base64Slice", Buffer::Base64Slice);
|
NODE_SET_PROTOTYPE_METHOD(constructor_template, "base64Slice", Buffer::Base64Slice);
|
||||||
NODE_SET_PROTOTYPE_METHOD(constructor_template, "slice", Buffer::Slice);
|
|
||||||
// TODO NODE_SET_PROTOTYPE_METHOD(t, "utf16Slice", Utf16Slice);
|
// TODO NODE_SET_PROTOTYPE_METHOD(t, "utf16Slice", Utf16Slice);
|
||||||
// copy
|
// copy
|
||||||
NODE_SET_PROTOTYPE_METHOD(constructor_template, "utf8Slice", Buffer::Utf8Slice);
|
NODE_SET_PROTOTYPE_METHOD(constructor_template, "utf8Slice", Buffer::Utf8Slice);
|
||||||
|
@ -41,7 +41,6 @@ class Buffer : public ObjectWrap {
|
|||||||
|
|
||||||
char* data();
|
char* data();
|
||||||
size_t length() const { return length_; }
|
size_t length() const { return length_; }
|
||||||
struct Blob_* blob() const { return blob_; }
|
|
||||||
|
|
||||||
int AsciiWrite(char *string, int offset, int length);
|
int AsciiWrite(char *string, int offset, int length);
|
||||||
int Utf8Write(char *string, int offset, int length);
|
int Utf8Write(char *string, int offset, int length);
|
||||||
@ -67,9 +66,9 @@ class Buffer : public ObjectWrap {
|
|||||||
Buffer(size_t length);
|
Buffer(size_t length);
|
||||||
Buffer(Buffer *parent, size_t start, size_t end);
|
Buffer(Buffer *parent, size_t start, size_t end);
|
||||||
|
|
||||||
size_t off_; // offset inside blob_
|
size_t off_;
|
||||||
size_t length_; // length inside blob_
|
size_t length_;
|
||||||
struct Blob_ *blob_;
|
char* data_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user