Browse Source

Blob struct should not contain actual data

This is to allow eventual realloc without messing up the data_ references in
all the slices.
v0.7.4-release
Ryan Dahl 15 years ago
parent
commit
85487c82d0
  1. 51
      src/node_buffer.cc
  2. 6
      src/node_buffer.h

51
src/node_buffer.cc

@ -47,19 +47,24 @@ Persistent<FunctionTemplate> Buffer::constructor_template;
struct Blob_ { struct Blob_ {
unsigned int refs; unsigned int refs;
size_t length; size_t length;
char data[1]; char *data;
}; };
typedef struct Blob_ Blob; typedef struct Blob_ Blob;
static inline Blob * blob_new(size_t length) { static inline Blob * blob_new(size_t length) {
size_t s = sizeof(Blob) - 1 + length; Blob * blob = (Blob*) malloc(sizeof(Blob));
Blob * blob = (Blob*) malloc(s);
if (!blob) return NULL; if (!blob) return NULL;
V8::AdjustAmountOfExternalAllocatedMemory(s);
blob->data = (char*) malloc(length);
if (!blob->data) {
free(blob);
return NULL;
}
V8::AdjustAmountOfExternalAllocatedMemory(sizeof(Blob) + length);
blob->length = length; blob->length = length;
blob->refs = 0; blob->refs = 0;
//fprintf(stderr, "alloc %d bytes\n", length);
return blob; return blob;
} }
@ -73,8 +78,8 @@ static inline void blob_unref(Blob *blob) {
assert(blob->refs > 0); assert(blob->refs > 0);
if (--blob->refs == 0) { if (--blob->refs == 0) {
//fprintf(stderr, "free %d bytes\n", blob->length); //fprintf(stderr, "free %d bytes\n", blob->length);
size_t s = sizeof(Blob) - 1 + blob->length; V8::AdjustAmountOfExternalAllocatedMemory(-(sizeof(Blob) + blob->length));
V8::AdjustAmountOfExternalAllocatedMemory(-s); free(blob->data);
free(blob); free(blob);
} }
} }
@ -133,9 +138,9 @@ Handle<Value> Buffer::New(const Arguments &args) {
} }
buffer->Wrap(args.This()); buffer->Wrap(args.This());
args.This()->SetIndexedPropertiesToExternalArrayData((void*)buffer->data_, args.This()->SetIndexedPropertiesToExternalArrayData(buffer->data(),
kExternalUnsignedByteArray, kExternalUnsignedByteArray,
buffer->length_); buffer->length());
args.This()->Set(length_symbol, Integer::New(buffer->length_)); args.This()->Set(length_symbol, Integer::New(buffer->length_));
return args.This(); return args.This();
} }
@ -143,8 +148,9 @@ Handle<Value> Buffer::New(const Arguments &args) {
Buffer::Buffer(size_t length) : ObjectWrap() { Buffer::Buffer(size_t length) : ObjectWrap() {
blob_ = blob_new(length); blob_ = blob_new(length);
off_ = 0;
length_ = length; length_ = length;
data_ = blob_->data;
blob_ref(blob_); blob_ref(blob_);
V8::AdjustAmountOfExternalAllocatedMemory(sizeof(Buffer)); V8::AdjustAmountOfExternalAllocatedMemory(sizeof(Buffer));
@ -157,9 +163,9 @@ Buffer::Buffer(Buffer *parent, size_t start, size_t end) : ObjectWrap() {
blob_ref(blob_); blob_ref(blob_);
assert(start <= end); assert(start <= end);
off_ = start;
length_ = end - start; length_ = end - start;
assert(length_ <= parent->length_); assert(length_ <= parent->length_);
data_ = parent->data_ + start;
V8::AdjustAmountOfExternalAllocatedMemory(sizeof(Buffer)); V8::AdjustAmountOfExternalAllocatedMemory(sizeof(Buffer));
} }
@ -173,12 +179,17 @@ Buffer::~Buffer() {
} }
char* Buffer::data() {
return blob_->data + off_;
}
Handle<Value> Buffer::BinarySlice(const Arguments &args) { Handle<Value> Buffer::BinarySlice(const Arguments &args) {
HandleScope scope; HandleScope scope;
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])
const char *data = const_cast<char*>(parent->data_ + start); const char *data = const_cast<char*>(parent->data() + start);
//Local<String> string = String::New(data, end - start); //Local<String> string = String::New(data, end - start);
Local<Value> b = Encode(data, end - start, BINARY); Local<Value> b = Encode(data, end - start, BINARY);
@ -200,7 +211,7 @@ Handle<Value> Buffer::AsciiSlice(const Arguments &args) {
assert(parent->blob_->refs >= 2); assert(parent->blob_->refs >= 2);
#endif #endif
const char *data = const_cast<char*>(parent->data_ + start); const char *data = const_cast<char*>(parent->data() + start);
Local<String> string = String::New(data, end - start); Local<String> string = String::New(data, end - start);
@ -212,7 +223,7 @@ Handle<Value> Buffer::Utf8Slice(const Arguments &args) {
HandleScope scope; HandleScope scope;
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])
const char *data = const_cast<char*>(parent->data_ + start); const char *data = const_cast<char*>(parent->data() + start);
Local<String> string = String::New(data, end - start); Local<String> string = String::New(data, end - start);
return scope.Close(string); return scope.Close(string);
} }
@ -295,7 +306,7 @@ Handle<Value> Buffer::Utf8Write(const Arguments &args) {
"Offset is out of bounds"))); "Offset is out of bounds")));
} }
const char *p = buffer->data_ + offset; const char *p = buffer->data() + offset;
int written = s->WriteUtf8((char*)p, buffer->length_ - offset); int written = s->WriteUtf8((char*)p, buffer->length_ - offset);
@ -323,7 +334,7 @@ Handle<Value> Buffer::AsciiWrite(const Arguments &args) {
"Offset is out of bounds"))); "Offset is out of bounds")));
} }
const char *p = buffer->data_ + offset; const char *p = buffer->data() + offset;
size_t towrite = MIN((unsigned long) s->Length(), buffer->length_ - offset); size_t towrite = MIN((unsigned long) s->Length(), buffer->length_ - offset);
@ -351,7 +362,7 @@ Handle<Value> Buffer::BinaryWrite(const Arguments &args) {
"Offset is out of bounds"))); "Offset is out of bounds")));
} }
char *p = (char*)buffer->data_ + offset; char *p = (char*)buffer->data() + offset;
size_t towrite = MIN((unsigned long) s->Length(), buffer->length_ - offset); size_t towrite = MIN((unsigned long) s->Length(), buffer->length_ - offset);
@ -393,7 +404,7 @@ Handle<Value> Buffer::Unpack(const Arguments &args) {
// 32bit unsigned integer in network byte order // 32bit unsigned integer in network byte order
case 'N': case 'N':
if (index + 3 >= buffer->length_) return OUT_OF_BOUNDS; if (index + 3 >= buffer->length_) return OUT_OF_BOUNDS;
uint32 = htonl(*(uint32_t*)(buffer->data_ + index)); uint32 = htonl(*(uint32_t*)(buffer->data() + index));
array->Set(Integer::New(i), Integer::NewFromUnsigned(uint32)); array->Set(Integer::New(i), Integer::NewFromUnsigned(uint32));
index += 4; index += 4;
break; break;
@ -401,7 +412,7 @@ Handle<Value> Buffer::Unpack(const Arguments &args) {
// 16bit unsigned integer in network byte order // 16bit unsigned integer in network byte order
case 'n': case 'n':
if (index + 1 >= buffer->length_) return OUT_OF_BOUNDS; if (index + 1 >= buffer->length_) return OUT_OF_BOUNDS;
uint16 = htons(*(uint16_t*)(buffer->data_ + index)); uint16 = htons(*(uint16_t*)(buffer->data() + index));
array->Set(Integer::New(i), Integer::NewFromUnsigned(uint16)); array->Set(Integer::New(i), Integer::NewFromUnsigned(uint16));
index += 2; index += 2;
break; break;
@ -409,7 +420,7 @@ Handle<Value> Buffer::Unpack(const Arguments &args) {
// a single octet, unsigned. // a single octet, unsigned.
case 'o': case 'o':
if (index >= buffer->length_) return OUT_OF_BOUNDS; if (index >= buffer->length_) return OUT_OF_BOUNDS;
uint8 = (uint8_t)buffer->data_[index]; uint8 = (uint8_t)buffer->data()[index];
array->Set(Integer::New(i), Integer::NewFromUnsigned(uint8)); array->Set(Integer::New(i), Integer::NewFromUnsigned(uint8));
index += 1; index += 1;
break; break;

6
src/node_buffer.h

@ -37,7 +37,7 @@ class Buffer : public ObjectWrap {
return constructor_template->HasInstance(obj); return constructor_template->HasInstance(obj);
} }
const char* data() const { return data_; } char* data();
size_t length() const { return length_; } size_t length() const { return length_; }
struct Blob_* blob() const { return blob_; } struct Blob_* blob() const { return blob_; }
@ -63,8 +63,8 @@ class Buffer : public ObjectWrap {
Buffer(Buffer *parent, size_t start, size_t end); Buffer(Buffer *parent, size_t start, size_t end);
~Buffer(); ~Buffer();
const char *data_; size_t off_; // offset inside blob_
size_t length_; size_t length_; // length inside blob_
struct Blob_ *blob_; struct Blob_ *blob_;
}; };

Loading…
Cancel
Save