@@ -24,109 +24,113 @@ using namespace v8;
24
24
static Persistent<String> length_symbol;
25
25
static Persistent<FunctionTemplate> constructor_template;
26
26
27
- /* A blob is a chunk of memory stored outside the V8 heap mirrored by an
27
+ /* A buffer is a chunk of memory stored outside the V8 heap, mirrored by an
28
28
* object in javascript. The object is not totally opaque, one can access
29
- * individual bytes with [] and one can slice the blob into substrings or
30
- * subblobs without copying memory.
29
+ * individual bytes with [] and slice it into substrings or sub-buffers
30
+ * without copying memory.
31
31
*
32
- * blob.asciiSlide(0, 3) // return an ascii encoded string - no memory iscopied
33
- * blob.slice (0, 3) // returns another blob - no memory is copied
32
+ * // return an ascii encoded string - no memory iscopied
33
+ * buffer.asciiSlide (0, 3)
34
34
*
35
- * Interally, each javascript blob object is backed by a "struct blob" object.
36
- * These "struct blob" objects are either the root object (in the case that
37
- * blob->root == NULL) or slice objects (in which case blob->root != NULL).
38
- * The root blob is only GCed once all it's slices are GCed.
35
+ * // returns another buffer - no memory is copied
36
+ * buffer.slice(0, 3)
37
+ *
38
+ * Interally, each javascript buffer object is backed by a "struct buffer"
39
+ * object. These "struct buffer" objects are either a root buffer (in the
40
+ * case that buffer->root == NULL) or slice objects (in which case
41
+ * buffer->root != NULL). A root buffer is only GCed once all its slices
42
+ * are GCed.
39
43
*/
40
44
41
- struct blob {
45
+ struct buffer {
42
46
Persistent<Object> handle; // both
43
47
bool weak; // both
44
- struct blob *root; // both (NULL for root)
48
+ struct buffer *root; // both (NULL for root)
45
49
size_t offset; // both (0 for root)
46
50
size_t length; // both
47
51
unsigned int refs; // root only
48
- char bytes[1 ]; // root only
52
+ char bytes[1 ]; // root only
49
53
};
50
54
51
55
52
- static inline struct blob * blob_root (blob *blob ) {
53
- return blob ->root ? blob ->root : blob ;
56
+ static inline struct buffer * buffer_root (buffer *buffer ) {
57
+ return buffer ->root ? buffer ->root : buffer ;
54
58
}
55
59
56
60
/* Determines the absolute position for a relative offset */
57
- static inline size_t blob_abs_off (blob *blob , size_t off) {
58
- struct blob *root = blob_root (blob );
61
+ static inline size_t buffer_abs_off (buffer *buffer , size_t off) {
62
+ struct buffer *root = buffer_root (buffer );
59
63
off += root->offset ;
60
64
return MIN (root->length , off);
61
65
}
62
66
63
67
64
- static inline void blob_ref (struct blob *blob ) {
65
- assert (blob ->root == NULL );
66
- blob ->refs ++;
68
+ static inline void buffer_ref (struct buffer *buffer ) {
69
+ assert (buffer ->root == NULL );
70
+ buffer ->refs ++;
67
71
}
68
72
69
73
70
- static inline void blob_unref (struct blob *blob ) {
71
- assert (blob ->root == NULL );
72
- assert (blob ->refs > 0 );
73
- blob ->refs --;
74
- if (blob ->refs == 0 && blob ->weak ) free (blob );
74
+ static inline void buffer_unref (struct buffer *buffer ) {
75
+ assert (buffer ->root == NULL );
76
+ assert (buffer ->refs > 0 );
77
+ buffer ->refs --;
78
+ if (buffer ->refs == 0 && buffer ->weak ) free (buffer );
75
79
}
76
80
77
81
78
- static inline struct blob * Unwrap (Handle <Value> val) {
82
+ static inline struct buffer * Unwrap (Handle <Value> val) {
79
83
assert (val->IsObject ());
80
84
HandleScope scope;
81
85
Local<Object> obj = val->ToObject ();
82
86
assert (obj->InternalFieldCount () == 1 );
83
87
Local<External> ext = Local<External>::Cast (obj->GetInternalField (0 ));
84
- return static_cast <struct blob *>(ext->Value ());
88
+ return static_cast <struct buffer *>(ext->Value ());
85
89
}
86
90
87
91
88
92
static void RootWeakCallback (Persistent<Value> value, void *data)
89
93
{
90
- struct blob *blob = static_cast <struct blob *>(data);
91
- assert (blob ->root == NULL ); // this is the root
92
- assert (value == blob ->handle );
93
- blob ->handle .Dispose ();
94
- if (blob ->refs ) {
95
- blob ->weak = true ;
94
+ struct buffer *buffer = static_cast <struct buffer *>(data);
95
+ assert (buffer ->root == NULL ); // this is the root
96
+ assert (value == buffer ->handle );
97
+ buffer ->handle .Dispose ();
98
+ if (buffer ->refs ) {
99
+ buffer ->weak = true ;
96
100
} else {
97
- free (blob );
101
+ free (buffer );
98
102
}
99
103
}
100
104
101
105
102
106
static void SliceWeakCallback (Persistent<Value> value, void *data)
103
107
{
104
- struct blob *blob = static_cast <struct blob *>(data);
105
- assert (blob ->root != NULL ); // this is a slice
106
- assert (value == blob ->handle );
107
- blob ->handle .Dispose ();
108
- blob_unref (blob ->root );
108
+ struct buffer *buffer = static_cast <struct buffer *>(data);
109
+ assert (buffer ->root != NULL ); // this is a slice
110
+ assert (value == buffer ->handle );
111
+ buffer ->handle .Dispose ();
112
+ buffer_unref (buffer ->root );
109
113
}
110
114
111
115
112
116
static Handle <Value> Constructor (const Arguments &args) {
113
117
HandleScope scope;
114
118
115
119
size_t length;
116
- struct blob *blob ;
120
+ struct buffer *buffer ;
117
121
118
122
if (constructor_template->HasInstance (args[0 ])) {
119
123
// slice slice
120
124
SLICE_ARGS (args[1 ], args[2 ])
121
125
122
- struct blob *parent = Unwrap (args[0 ]);
126
+ struct buffer *parent = Unwrap (args[0 ]);
123
127
124
- size_t start_abs = blob_abs_off (parent, start);
125
- size_t end_abs = blob_abs_off (parent, end);
128
+ size_t start_abs = buffer_abs_off (parent, start);
129
+ size_t end_abs = buffer_abs_off (parent, end);
126
130
assert (start_abs <= end_abs);
127
131
length = end_abs - start_abs;
128
132
129
- void *d = malloc (sizeof (struct blob ));
133
+ void *d = malloc (sizeof (struct buffer ));
130
134
131
135
if (!d) {
132
136
V8::LowMemoryNotification ();
@@ -135,17 +139,17 @@ static Handle<Value> Constructor(const Arguments &args) {
135
139
136
140
}
137
141
138
- blob = static_cast <struct blob *>(d);
142
+ buffer = static_cast <struct buffer *>(d);
139
143
140
- blob ->length = length;
141
- blob ->offset = start_abs;
142
- blob ->weak = false ;
143
- blob ->refs = 0 ;
144
- blob ->root = blob_root (parent);
145
- blob ->handle = Persistent<Object>::New (args.This ());
146
- blob ->handle .MakeWeak (blob , SliceWeakCallback);
144
+ buffer ->length = length;
145
+ buffer ->offset = start_abs;
146
+ buffer ->weak = false ;
147
+ buffer ->refs = 0 ;
148
+ buffer ->root = buffer_root (parent);
149
+ buffer ->handle = Persistent<Object>::New (args.This ());
150
+ buffer ->handle .MakeWeak (buffer , SliceWeakCallback);
147
151
148
- blob_ref (blob ->root );
152
+ buffer_ref (buffer ->root );
149
153
} else {
150
154
// Root slice
151
155
@@ -157,31 +161,31 @@ static Handle<Value> Constructor(const Arguments &args) {
157
161
}
158
162
159
163
// TODO alignment. modify the length?
160
- void *d = malloc (sizeof (struct blob ) + length - 1 );
164
+ void *d = malloc (sizeof (struct buffer ) + length - 1 );
161
165
162
166
if (!d) {
163
167
V8::LowMemoryNotification ();
164
168
return ThrowException (Exception::Error (
165
169
String::New (" Could not allocate enough memory" )));
166
170
}
167
171
168
- blob = static_cast <struct blob *>(d);
172
+ buffer = static_cast <struct buffer *>(d);
169
173
170
- blob ->offset = 0 ;
171
- blob ->length = length;
172
- blob ->weak = false ;
173
- blob ->refs = 0 ;
174
- blob ->root = NULL ;
175
- blob ->handle = Persistent<Object>::New (args.This ());
176
- blob ->handle .MakeWeak (blob , RootWeakCallback);
174
+ buffer ->offset = 0 ;
175
+ buffer ->length = length;
176
+ buffer ->weak = false ;
177
+ buffer ->refs = 0 ;
178
+ buffer ->root = NULL ;
179
+ buffer ->handle = Persistent<Object>::New (args.This ());
180
+ buffer ->handle .MakeWeak (buffer , RootWeakCallback);
177
181
}
178
182
179
- args.This ()->SetInternalField (0 , v8::External::New (blob ));
183
+ args.This ()->SetInternalField (0 , v8::External::New (buffer ));
180
184
181
- struct blob *root = blob_root (blob );
185
+ struct buffer *root = buffer_root (buffer );
182
186
183
187
args.This ()->
184
- SetIndexedPropertiesToExternalArrayData (&root->bytes + blob ->offset ,
188
+ SetIndexedPropertiesToExternalArrayData (&root->bytes + buffer ->offset ,
185
189
kExternalUnsignedByteArray ,
186
190
length);
187
191
@@ -194,16 +198,16 @@ static Handle<Value> Constructor(const Arguments &args) {
194
198
class AsciiSliceExt : public String ::ExternalAsciiStringResource {
195
199
public:
196
200
197
- AsciiSliceExt (struct blob *root, size_t start, size_t end)
201
+ AsciiSliceExt (struct buffer *root, size_t start, size_t end)
198
202
{
199
203
data_ = root->bytes + start;
200
204
len_ = end - start;
201
205
root_ = root;
202
- blob_ref (root_);
206
+ buffer_ref (root_);
203
207
}
204
208
205
209
~AsciiSliceExt () {
206
- blob_unref (root_);
210
+ buffer_unref (root_);
207
211
}
208
212
209
213
const char * data () const {
@@ -217,7 +221,7 @@ class AsciiSliceExt: public String::ExternalAsciiStringResource {
217
221
private:
218
222
const char *data_;
219
223
size_t len_;
220
- struct blob *root_;
224
+ struct buffer *root_;
221
225
};
222
226
223
227
static Handle <Value> AsciiSlice (const Arguments &args) {
@@ -226,17 +230,17 @@ static Handle<Value> AsciiSlice(const Arguments &args) {
226
230
SLICE_ARGS (args[0 ], args[1 ])
227
231
228
232
assert (args.This ()->InternalFieldCount () == 1 );
229
- struct blob *parent = Unwrap (args.This ());
233
+ struct buffer *parent = Unwrap (args.This ());
230
234
231
- size_t start_abs = blob_abs_off (parent, start);
232
- size_t end_abs = blob_abs_off (parent, end);
235
+ size_t start_abs = buffer_abs_off (parent, start);
236
+ size_t end_abs = buffer_abs_off (parent, end);
233
237
234
238
assert (start_abs <= end_abs);
235
239
236
- AsciiSliceExt *s = new AsciiSliceExt (blob_root (parent), start_abs, end_abs);
240
+ AsciiSliceExt *s = new AsciiSliceExt (buffer_root (parent), start_abs, end_abs);
237
241
Local<String> string = String::NewExternal (s);
238
242
239
- struct blob *root = blob_root (parent);
243
+ struct buffer *root = buffer_root (parent);
240
244
assert (root->refs > 0 );
241
245
242
246
return scope.Close (string);
@@ -247,12 +251,12 @@ static Handle<Value> Utf8Slice(const Arguments &args) {
247
251
248
252
SLICE_ARGS (args[0 ], args[1 ])
249
253
250
- struct blob *parent = Unwrap (args.This ());
251
- size_t start_abs = blob_abs_off (parent, start);
252
- size_t end_abs = blob_abs_off (parent, end);
254
+ struct buffer *parent = Unwrap (args.This ());
255
+ size_t start_abs = buffer_abs_off (parent, start);
256
+ size_t end_abs = buffer_abs_off (parent, end);
253
257
assert (start_abs <= end_abs);
254
258
255
- struct blob *root = blob_root (parent);
259
+ struct buffer *root = buffer_root (parent);
256
260
257
261
Local<String> string =
258
262
String::New (reinterpret_cast <const char *>(&root->bytes + start_abs),
@@ -271,15 +275,15 @@ static Handle<Value> Slice(const Arguments &args) {
271
275
return scope.Close (slice);
272
276
}
273
277
274
- void InitBlob (Handle <Object> target) {
278
+ void InitBuffer (Handle <Object> target) {
275
279
HandleScope scope;
276
280
277
281
length_symbol = Persistent<String>::New (String::NewSymbol (" length" ));
278
282
279
283
Local<FunctionTemplate> t = FunctionTemplate::New (Constructor);
280
284
constructor_template = Persistent<FunctionTemplate>::New (t);
281
285
constructor_template->InstanceTemplate ()->SetInternalFieldCount (1 );
282
- constructor_template->SetClassName (String::NewSymbol (" Blob " ));
286
+ constructor_template->SetClassName (String::NewSymbol (" Buffer " ));
283
287
284
288
// copy free
285
289
NODE_SET_PROTOTYPE_METHOD (constructor_template, " asciiSlice" , AsciiSlice);
@@ -288,7 +292,7 @@ void InitBlob(Handle<Object> target) {
288
292
// copy
289
293
NODE_SET_PROTOTYPE_METHOD (constructor_template, " utf8Slice" , Utf8Slice);
290
294
291
- target->Set (String::NewSymbol (" Blob " ), constructor_template->GetFunction ());
295
+ target->Set (String::NewSymbol (" Buffer " ), constructor_template->GetFunction ());
292
296
}
293
297
294
298
} // namespace node
0 commit comments