iobuffer 1.1.1 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/ext/extconf.rb +1 -1
- data/ext/iobuffer.c +372 -371
- data/lib/iobuffer/version.rb +1 -1
- metadata +8 -9
- data/lib/iobuffer_ext.bundle +0 -0
data/ext/extconf.rb
CHANGED
data/ext/iobuffer.c
CHANGED
@@ -29,16 +29,16 @@
|
|
29
29
|
static unsigned default_node_size = DEFAULT_NODE_SIZE;
|
30
30
|
|
31
31
|
struct buffer {
|
32
|
-
|
33
|
-
|
34
|
-
|
32
|
+
unsigned size, node_size;
|
33
|
+
struct buffer_node *head, *tail;
|
34
|
+
struct buffer_node *pool_head, *pool_tail;
|
35
35
|
|
36
36
|
};
|
37
37
|
|
38
38
|
struct buffer_node {
|
39
|
-
|
40
|
-
|
41
|
-
|
39
|
+
unsigned start, end;
|
40
|
+
struct buffer_node *next;
|
41
|
+
unsigned char data[0];
|
42
42
|
};
|
43
43
|
|
44
44
|
static VALUE cIO_Buffer = Qnil;
|
@@ -83,48 +83,48 @@ static int buffer_write_to(struct buffer * buf, int fd);
|
|
83
83
|
void
|
84
84
|
Init_iobuffer_ext()
|
85
85
|
{
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
86
|
+
cIO_Buffer = rb_define_class_under(rb_cIO, "Buffer", rb_cObject);
|
87
|
+
rb_define_alloc_func(cIO_Buffer, IO_Buffer_allocate);
|
88
|
+
|
89
|
+
rb_define_singleton_method(cIO_Buffer, "default_node_size",
|
90
|
+
IO_Buffer_default_node_size, 0);
|
91
|
+
rb_define_singleton_method(cIO_Buffer, "default_node_size=",
|
92
|
+
IO_Buffer_set_default_node_size, 1);
|
93
|
+
|
94
|
+
rb_define_method(cIO_Buffer, "initialize", IO_Buffer_initialize, -1);
|
95
|
+
rb_define_method(cIO_Buffer, "clear", IO_Buffer_clear, 0);
|
96
|
+
rb_define_method(cIO_Buffer, "size", IO_Buffer_size, 0);
|
97
|
+
rb_define_method(cIO_Buffer, "empty?", IO_Buffer_empty, 0);
|
98
|
+
rb_define_method(cIO_Buffer, "<<", IO_Buffer_append, 1);
|
99
|
+
rb_define_method(cIO_Buffer, "append", IO_Buffer_append, 1);
|
100
|
+
rb_define_method(cIO_Buffer, "write", IO_Buffer_append, 1);
|
101
|
+
rb_define_method(cIO_Buffer, "prepend", IO_Buffer_prepend, 1);
|
102
|
+
rb_define_method(cIO_Buffer, "read", IO_Buffer_read, -1);
|
103
|
+
rb_define_method(cIO_Buffer, "read_frame", IO_Buffer_read_frame, 2);
|
104
|
+
rb_define_method(cIO_Buffer, "to_str", IO_Buffer_to_str, 0);
|
105
|
+
rb_define_method(cIO_Buffer, "read_from", IO_Buffer_read_from, 1);
|
106
|
+
rb_define_method(cIO_Buffer, "write_to", IO_Buffer_write_to, 1);
|
107
|
+
|
108
|
+
rb_define_const(cIO_Buffer, "MAX_SIZE", INT2NUM(MAX_BUFFER_SIZE));
|
109
109
|
}
|
110
110
|
|
111
111
|
static VALUE
|
112
112
|
IO_Buffer_allocate(VALUE klass)
|
113
113
|
{
|
114
|
-
|
114
|
+
return Data_Wrap_Struct(klass, IO_Buffer_mark, IO_Buffer_free, buffer_new());
|
115
115
|
}
|
116
116
|
|
117
117
|
static void
|
118
118
|
IO_Buffer_mark(struct buffer * buf)
|
119
119
|
{
|
120
|
-
|
121
|
-
|
120
|
+
/* Naively discard the memory pool whenever Ruby garbage collects */
|
121
|
+
buffer_free_pool(buf);
|
122
122
|
}
|
123
123
|
|
124
124
|
static void
|
125
125
|
IO_Buffer_free(struct buffer * buf)
|
126
126
|
{
|
127
|
-
|
127
|
+
buffer_free(buf);
|
128
128
|
}
|
129
129
|
|
130
130
|
/**
|
@@ -136,7 +136,7 @@ IO_Buffer_free(struct buffer * buf)
|
|
136
136
|
static VALUE
|
137
137
|
IO_Buffer_default_node_size(VALUE klass)
|
138
138
|
{
|
139
|
-
|
139
|
+
return UINT2NUM(default_node_size);
|
140
140
|
}
|
141
141
|
|
142
142
|
/*
|
@@ -146,13 +146,13 @@ IO_Buffer_default_node_size(VALUE klass)
|
|
146
146
|
static unsigned
|
147
147
|
convert_node_size(VALUE size)
|
148
148
|
{
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
149
|
+
if (
|
150
|
+
rb_funcall(size, rb_intern("<"), 1, INT2NUM(1)) == Qtrue ||
|
151
|
+
rb_funcall(size, rb_intern(">"), 1, INT2NUM(MAX_BUFFER_SIZE)) == Qtrue
|
152
|
+
)
|
153
|
+
rb_raise(rb_eArgError, "invalid buffer size");
|
154
154
|
|
155
|
-
|
155
|
+
return (unsigned) NUM2INT(size);
|
156
156
|
}
|
157
157
|
|
158
158
|
/**
|
@@ -164,9 +164,9 @@ convert_node_size(VALUE size)
|
|
164
164
|
static VALUE
|
165
165
|
IO_Buffer_set_default_node_size(VALUE klass, VALUE size)
|
166
166
|
{
|
167
|
-
|
167
|
+
default_node_size = convert_node_size(size);
|
168
168
|
|
169
|
-
|
169
|
+
return size;
|
170
170
|
}
|
171
171
|
|
172
172
|
/**
|
@@ -178,22 +178,22 @@ IO_Buffer_set_default_node_size(VALUE klass, VALUE size)
|
|
178
178
|
static VALUE
|
179
179
|
IO_Buffer_initialize(int argc, VALUE * argv, VALUE self)
|
180
180
|
{
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
181
|
+
VALUE node_size_obj;
|
182
|
+
struct buffer *buf;
|
183
|
+
|
184
|
+
if (rb_scan_args(argc, argv, "01", &node_size_obj) == 1) {
|
185
|
+
Data_Get_Struct(self, struct buffer, buf);
|
186
|
+
|
187
|
+
/*
|
188
|
+
* Make sure we're not changing the buffer size after data
|
189
|
+
* has been allocated
|
190
|
+
*/
|
191
|
+
assert(!buf->head);
|
192
|
+
assert(!buf->pool_head);
|
193
|
+
|
194
|
+
buf->node_size = convert_node_size(node_size_obj);
|
195
|
+
}
|
196
|
+
return Qnil;
|
197
197
|
}
|
198
198
|
|
199
199
|
/**
|
@@ -205,12 +205,12 @@ IO_Buffer_initialize(int argc, VALUE * argv, VALUE self)
|
|
205
205
|
static VALUE
|
206
206
|
IO_Buffer_clear(VALUE self)
|
207
207
|
{
|
208
|
-
|
209
|
-
|
208
|
+
struct buffer *buf;
|
209
|
+
Data_Get_Struct(self, struct buffer, buf);
|
210
210
|
|
211
|
-
|
211
|
+
buffer_clear(buf);
|
212
212
|
|
213
|
-
|
213
|
+
return Qnil;
|
214
214
|
}
|
215
215
|
|
216
216
|
/**
|
@@ -222,10 +222,10 @@ IO_Buffer_clear(VALUE self)
|
|
222
222
|
static VALUE
|
223
223
|
IO_Buffer_size(VALUE self)
|
224
224
|
{
|
225
|
-
|
226
|
-
|
225
|
+
struct buffer *buf;
|
226
|
+
Data_Get_Struct(self, struct buffer, buf);
|
227
227
|
|
228
|
-
|
228
|
+
return INT2NUM(buf->size);
|
229
229
|
}
|
230
230
|
|
231
231
|
/**
|
@@ -237,10 +237,10 @@ IO_Buffer_size(VALUE self)
|
|
237
237
|
static VALUE
|
238
238
|
IO_Buffer_empty(VALUE self)
|
239
239
|
{
|
240
|
-
|
241
|
-
|
240
|
+
struct buffer *buf;
|
241
|
+
Data_Get_Struct(self, struct buffer, buf);
|
242
242
|
|
243
|
-
|
243
|
+
return buf->size > 0 ? Qfalse : Qtrue;
|
244
244
|
}
|
245
245
|
|
246
246
|
/**
|
@@ -252,14 +252,14 @@ IO_Buffer_empty(VALUE self)
|
|
252
252
|
static VALUE
|
253
253
|
IO_Buffer_append(VALUE self, VALUE data)
|
254
254
|
{
|
255
|
-
|
256
|
-
|
255
|
+
struct buffer *buf;
|
256
|
+
Data_Get_Struct(self, struct buffer, buf);
|
257
257
|
|
258
|
-
|
259
|
-
|
260
|
-
|
258
|
+
/* Is this needed? Never seen anyone else do it... */
|
259
|
+
data = rb_convert_type(data, T_STRING, "String", "to_str");
|
260
|
+
buffer_append(buf, RSTRING_PTR(data), RSTRING_LEN(data));
|
261
261
|
|
262
|
-
|
262
|
+
return data;
|
263
263
|
}
|
264
264
|
|
265
265
|
/**
|
@@ -271,13 +271,13 @@ IO_Buffer_append(VALUE self, VALUE data)
|
|
271
271
|
static VALUE
|
272
272
|
IO_Buffer_prepend(VALUE self, VALUE data)
|
273
273
|
{
|
274
|
-
|
275
|
-
|
274
|
+
struct buffer *buf;
|
275
|
+
Data_Get_Struct(self, struct buffer, buf);
|
276
276
|
|
277
|
-
|
278
|
-
|
277
|
+
data = rb_convert_type(data, T_STRING, "String", "to_str");
|
278
|
+
buffer_prepend(buf, RSTRING_PTR(data), RSTRING_LEN(data));
|
279
279
|
|
280
|
-
|
280
|
+
return data;
|
281
281
|
}
|
282
282
|
|
283
283
|
/**
|
@@ -294,28 +294,28 @@ IO_Buffer_prepend(VALUE self, VALUE data)
|
|
294
294
|
static VALUE
|
295
295
|
IO_Buffer_read(int argc, VALUE * argv, VALUE self)
|
296
296
|
{
|
297
|
-
|
298
|
-
|
299
|
-
|
297
|
+
VALUE length_obj, str;
|
298
|
+
int length;
|
299
|
+
struct buffer *buf;
|
300
300
|
|
301
|
-
|
301
|
+
Data_Get_Struct(self, struct buffer, buf);
|
302
302
|
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
303
|
+
if (rb_scan_args(argc, argv, "01", &length_obj) == 1) {
|
304
|
+
length = NUM2INT(length_obj);
|
305
|
+
if(length < 1)
|
306
|
+
rb_raise(rb_eArgError, "length must be greater than zero");
|
307
|
+
if(length > buf->size)
|
308
|
+
length = buf->size;
|
309
|
+
} else
|
310
|
+
length = buf->size;
|
311
311
|
|
312
|
-
|
313
|
-
|
312
|
+
if(buf->size == 0)
|
313
|
+
return rb_str_new2("");
|
314
314
|
|
315
|
-
|
316
|
-
|
315
|
+
str = rb_str_new(0, length);
|
316
|
+
buffer_read(buf, RSTRING_PTR(str), length);
|
317
317
|
|
318
|
-
|
318
|
+
return str;
|
319
319
|
}
|
320
320
|
|
321
321
|
/**
|
@@ -331,16 +331,16 @@ IO_Buffer_read(int argc, VALUE * argv, VALUE self)
|
|
331
331
|
static VALUE
|
332
332
|
IO_Buffer_read_frame(VALUE self, VALUE data, VALUE mark)
|
333
333
|
{
|
334
|
-
|
335
|
-
|
334
|
+
char mark_c = (char) NUM2INT(mark);
|
335
|
+
struct buffer *buf;
|
336
336
|
|
337
|
-
|
337
|
+
Data_Get_Struct(self, struct buffer, buf);
|
338
338
|
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
339
|
+
if (buffer_read_frame(buf, data, mark_c)) {
|
340
|
+
return Qtrue;
|
341
|
+
} else {
|
342
|
+
return Qfalse;
|
343
|
+
}
|
344
344
|
}
|
345
345
|
|
346
346
|
/**
|
@@ -352,15 +352,15 @@ IO_Buffer_read_frame(VALUE self, VALUE data, VALUE mark)
|
|
352
352
|
static VALUE
|
353
353
|
IO_Buffer_to_str(VALUE self)
|
354
354
|
{
|
355
|
-
|
356
|
-
|
355
|
+
VALUE str;
|
356
|
+
struct buffer *buf;
|
357
357
|
|
358
|
-
|
358
|
+
Data_Get_Struct(self, struct buffer, buf);
|
359
359
|
|
360
|
-
|
361
|
-
|
360
|
+
str = rb_str_new(0, buf->size);
|
361
|
+
buffer_copy(buf, RSTRING_PTR(str), buf->size);
|
362
362
|
|
363
|
-
|
363
|
+
return str;
|
364
364
|
}
|
365
365
|
|
366
366
|
/**
|
@@ -374,20 +374,20 @@ IO_Buffer_to_str(VALUE self)
|
|
374
374
|
static VALUE
|
375
375
|
IO_Buffer_read_from(VALUE self, VALUE io)
|
376
376
|
{
|
377
|
-
|
378
|
-
|
377
|
+
struct buffer *buf;
|
378
|
+
int ret;
|
379
379
|
#if HAVE_RB_IO_T
|
380
|
-
|
380
|
+
rb_io_t *fptr;
|
381
381
|
#else
|
382
|
-
|
382
|
+
OpenFile *fptr;
|
383
383
|
#endif
|
384
384
|
|
385
|
-
|
386
|
-
|
387
|
-
|
385
|
+
Data_Get_Struct(self, struct buffer, buf);
|
386
|
+
GetOpenFile(rb_convert_type(io, T_FILE, "IO", "to_io"), fptr);
|
387
|
+
rb_io_set_nonblock(fptr);
|
388
388
|
|
389
|
-
|
390
|
-
|
389
|
+
ret = buffer_read_from(buf, FPTR_TO_FD(fptr));
|
390
|
+
return ret == -1 ? Qnil : INT2NUM(ret);
|
391
391
|
}
|
392
392
|
|
393
393
|
/**
|
@@ -401,18 +401,18 @@ IO_Buffer_read_from(VALUE self, VALUE io)
|
|
401
401
|
static VALUE
|
402
402
|
IO_Buffer_write_to(VALUE self, VALUE io)
|
403
403
|
{
|
404
|
-
|
404
|
+
struct buffer *buf;
|
405
405
|
#if HAVE_RB_IO_T
|
406
|
-
|
406
|
+
rb_io_t *fptr;
|
407
407
|
#else
|
408
|
-
|
408
|
+
OpenFile *fptr;
|
409
409
|
#endif
|
410
410
|
|
411
|
-
|
412
|
-
|
413
|
-
|
411
|
+
Data_Get_Struct(self, struct buffer, buf);
|
412
|
+
GetOpenFile(rb_convert_type(io, T_FILE, "IO", "to_io"), fptr);
|
413
|
+
rb_io_set_nonblock(fptr);
|
414
414
|
|
415
|
-
|
415
|
+
return INT2NUM(buffer_write_to(buf, FPTR_TO_FD(fptr)));
|
416
416
|
}
|
417
417
|
|
418
418
|
/*
|
@@ -424,198 +424,198 @@ IO_Buffer_write_to(VALUE self, VALUE io)
|
|
424
424
|
static struct buffer *
|
425
425
|
buffer_new(void)
|
426
426
|
{
|
427
|
-
|
427
|
+
struct buffer *buf;
|
428
428
|
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
429
|
+
buf = (struct buffer *) xmalloc(sizeof(struct buffer));
|
430
|
+
buf->head = buf->tail = buf->pool_head = buf->pool_tail = 0;
|
431
|
+
buf->size = 0;
|
432
|
+
buf->node_size = default_node_size;
|
433
433
|
|
434
|
-
|
434
|
+
return buf;
|
435
435
|
}
|
436
436
|
|
437
437
|
/* Clear all data from a buffer */
|
438
438
|
static void
|
439
439
|
buffer_clear(struct buffer * buf)
|
440
440
|
{
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
441
|
+
/* Move everything into the buffer pool */
|
442
|
+
if (!buf->pool_tail) {
|
443
|
+
buf->pool_head = buf->pool_tail = buf->head;
|
444
|
+
} else {
|
445
|
+
buf->pool_tail->next = buf->head;
|
446
|
+
}
|
447
|
+
|
448
|
+
buf->head = buf->tail = 0;
|
449
|
+
buf->size = 0;
|
450
450
|
}
|
451
451
|
|
452
452
|
/* Free a buffer */
|
453
453
|
static void
|
454
454
|
buffer_free(struct buffer * buf)
|
455
455
|
{
|
456
|
-
|
457
|
-
|
456
|
+
buffer_clear(buf);
|
457
|
+
buffer_free_pool(buf);
|
458
458
|
|
459
|
-
|
459
|
+
free(buf);
|
460
460
|
}
|
461
461
|
|
462
462
|
/* Free the memory pool */
|
463
463
|
static void
|
464
464
|
buffer_free_pool(struct buffer * buf)
|
465
465
|
{
|
466
|
-
|
466
|
+
struct buffer_node *tmp;
|
467
467
|
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
468
|
+
while (buf->pool_head) {
|
469
|
+
tmp = buf->pool_head;
|
470
|
+
buf->pool_head = tmp->next;
|
471
|
+
free(tmp);
|
472
|
+
}
|
473
473
|
|
474
|
-
|
474
|
+
buf->pool_tail = 0;
|
475
475
|
}
|
476
476
|
|
477
477
|
/* Create a new buffer_node (or pull one from the memory pool) */
|
478
478
|
static struct buffer_node *
|
479
479
|
buffer_node_new(struct buffer * buf)
|
480
480
|
{
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
481
|
+
struct buffer_node *node;
|
482
|
+
|
483
|
+
/* Pull from the memory pool if available */
|
484
|
+
if (buf->pool_head) {
|
485
|
+
node = buf->pool_head;
|
486
|
+
buf->pool_head = node->next;
|
487
|
+
|
488
|
+
if (node->next)
|
489
|
+
node->next = 0;
|
490
|
+
else
|
491
|
+
buf->pool_tail = 0;
|
492
|
+
} else {
|
493
|
+
node = (struct buffer_node *) xmalloc(sizeof(struct buffer_node) + buf->node_size);
|
494
|
+
node->next = 0;
|
495
|
+
}
|
496
|
+
|
497
|
+
node->start = node->end = 0;
|
498
|
+
return node;
|
499
499
|
}
|
500
500
|
|
501
501
|
/* Free a buffer node (i.e. return it to the memory pool) */
|
502
502
|
static void
|
503
503
|
buffer_node_free(struct buffer * buf, struct buffer_node * node)
|
504
504
|
{
|
505
|
-
|
506
|
-
|
505
|
+
node->next = buf->pool_head;
|
506
|
+
buf->pool_head = node;
|
507
507
|
|
508
|
-
|
509
|
-
|
510
|
-
|
508
|
+
if (!buf->pool_tail) {
|
509
|
+
buf->pool_tail = node;
|
510
|
+
}
|
511
511
|
}
|
512
512
|
|
513
513
|
/* Prepend data to the front of the buffer */
|
514
514
|
static void
|
515
515
|
buffer_prepend(struct buffer * buf, char *str, unsigned len)
|
516
516
|
{
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
517
|
+
struct buffer_node *node, *tmp;
|
518
|
+
buf->size += len;
|
519
|
+
|
520
|
+
/* If it fits in the beginning of the head */
|
521
|
+
if (buf->head && buf->head->start >= len) {
|
522
|
+
buf->head->start -= len;
|
523
|
+
memcpy(buf->head->data + buf->head->start, str, len);
|
524
|
+
} else {
|
525
|
+
node = buffer_node_new(buf);
|
526
|
+
node->next = buf->head;
|
527
|
+
buf->head = node;
|
528
|
+
if (!buf->tail)
|
529
|
+
buf->tail = node;
|
530
|
+
|
531
|
+
while (len > buf->node_size) {
|
532
|
+
memcpy(node->data, str, buf->node_size);
|
533
|
+
node->end = buf->node_size;
|
534
|
+
|
535
|
+
tmp = buffer_node_new(buf);
|
536
|
+
tmp->next = node->next;
|
537
|
+
node->next = tmp;
|
538
|
+
|
539
|
+
if (buf->tail == node)
|
540
|
+
buf->tail = tmp;
|
541
|
+
node = tmp;
|
542
|
+
|
543
|
+
str += buf->node_size;
|
544
|
+
len -= buf->node_size;
|
545
|
+
}
|
546
|
+
|
547
|
+
if (len > 0) {
|
548
|
+
memcpy(node->data, str, len);
|
549
|
+
node->end = len;
|
550
|
+
}
|
551
|
+
}
|
552
552
|
}
|
553
553
|
|
554
554
|
/* Append data to the front of the buffer */
|
555
555
|
static void
|
556
556
|
buffer_append(struct buffer * buf, char *str, unsigned len)
|
557
557
|
{
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
558
|
+
unsigned nbytes;
|
559
|
+
buf->size += len;
|
560
|
+
|
561
|
+
/* If it fits in the remaining space in the tail */
|
562
|
+
if (buf->tail && len <= buf->node_size - buf->tail->end) {
|
563
|
+
memcpy(buf->tail->data + buf->tail->end, str, len);
|
564
|
+
buf->tail->end += len;
|
565
|
+
return;
|
566
|
+
}
|
567
|
+
/* Empty list needs initialized */
|
568
|
+
if (!buf->head) {
|
569
|
+
buf->head = buffer_node_new(buf);
|
570
|
+
buf->tail = buf->head;
|
571
|
+
}
|
572
|
+
/* Build links out of the data */
|
573
|
+
while (len > 0) {
|
574
|
+
nbytes = buf->node_size - buf->tail->end;
|
575
|
+
if (len < nbytes)
|
576
|
+
nbytes = len;
|
577
|
+
|
578
|
+
memcpy(buf->tail->data + buf->tail->end, str, nbytes);
|
579
|
+
str += nbytes;
|
580
|
+
len -= nbytes;
|
581
|
+
|
582
|
+
buf->tail->end += nbytes;
|
583
|
+
|
584
|
+
if (len > 0) {
|
585
|
+
buf->tail->next = buffer_node_new(buf);
|
586
|
+
buf->tail = buf->tail->next;
|
587
|
+
}
|
588
|
+
}
|
589
589
|
}
|
590
590
|
|
591
591
|
/* Read data from the buffer (and clear what we've read) */
|
592
592
|
static void
|
593
593
|
buffer_read(struct buffer * buf, char *str, unsigned len)
|
594
594
|
{
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
595
|
+
unsigned nbytes;
|
596
|
+
struct buffer_node *tmp;
|
597
|
+
|
598
|
+
while (buf->size > 0 && len > 0) {
|
599
|
+
nbytes = buf->head->end - buf->head->start;
|
600
|
+
if (len < nbytes)
|
601
|
+
nbytes = len;
|
602
|
+
|
603
|
+
memcpy(str, buf->head->data + buf->head->start, nbytes);
|
604
|
+
str += nbytes;
|
605
|
+
len -= nbytes;
|
606
|
+
|
607
|
+
buf->head->start += nbytes;
|
608
|
+
buf->size -= nbytes;
|
609
|
+
|
610
|
+
if (buf->head->start == buf->head->end) {
|
611
|
+
tmp = buf->head;
|
612
|
+
buf->head = tmp->next;
|
613
|
+
buffer_node_free(buf, tmp);
|
614
|
+
|
615
|
+
if (!buf->head)
|
616
|
+
buf->tail = 0;
|
617
|
+
}
|
618
|
+
}
|
619
619
|
}
|
620
620
|
|
621
621
|
/*
|
@@ -626,101 +626,101 @@ buffer_read(struct buffer * buf, char *str, unsigned len)
|
|
626
626
|
static int
|
627
627
|
buffer_read_frame(struct buffer * buf, VALUE str, char frame_mark)
|
628
628
|
{
|
629
|
-
|
630
|
-
|
629
|
+
unsigned nbytes = 0;
|
630
|
+
struct buffer_node *tmp;
|
631
631
|
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
632
|
+
while (buf->size > 0) {
|
633
|
+
struct buffer_node *head = buf->head;
|
634
|
+
char *loc, *s = head->data + head->start, *e = head->data + head->end;
|
635
|
+
nbytes = e - s;
|
636
636
|
|
637
|
-
|
637
|
+
loc = memchr(s, frame_mark, nbytes);
|
638
638
|
|
639
|
-
|
640
|
-
|
641
|
-
|
639
|
+
if (loc) {
|
640
|
+
nbytes = loc - s + 1;
|
641
|
+
}
|
642
642
|
|
643
|
-
|
644
|
-
|
643
|
+
/* Copy less than everything if we found a frame byte */
|
644
|
+
rb_str_cat(str, s, nbytes);
|
645
645
|
|
646
|
-
|
647
|
-
|
648
|
-
|
646
|
+
/* Fixup the buffer pointers to indicate the bytes were consumed */
|
647
|
+
head->start += nbytes;
|
648
|
+
buf->size -= nbytes;
|
649
649
|
|
650
|
-
|
651
|
-
|
652
|
-
|
650
|
+
if (head->start == head->end) {
|
651
|
+
buf->head = head->next;
|
652
|
+
buffer_node_free(buf, head);
|
653
653
|
|
654
|
-
|
655
|
-
|
656
|
-
|
654
|
+
if (!buf->head)
|
655
|
+
buf->tail = 0;
|
656
|
+
}
|
657
657
|
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
658
|
+
if (loc) {
|
659
|
+
return 1;
|
660
|
+
}
|
661
|
+
}
|
662
662
|
|
663
|
-
|
663
|
+
return 0;
|
664
664
|
}
|
665
665
|
|
666
666
|
/* Copy data from the buffer without clearing it */
|
667
667
|
static void
|
668
668
|
buffer_copy(struct buffer * buf, char *str, unsigned len)
|
669
669
|
{
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
670
|
+
unsigned nbytes;
|
671
|
+
struct buffer_node *node;
|
672
|
+
|
673
|
+
node = buf->head;
|
674
|
+
while (node && len > 0) {
|
675
|
+
nbytes = node->end - node->start;
|
676
|
+
if (len < nbytes)
|
677
|
+
nbytes = len;
|
678
|
+
|
679
|
+
memcpy(str, node->data + node->start, nbytes);
|
680
|
+
str += nbytes;
|
681
|
+
len -= nbytes;
|
682
|
+
|
683
|
+
if (node->start + nbytes == node->end)
|
684
|
+
node = node->next;
|
685
|
+
}
|
686
686
|
}
|
687
687
|
|
688
688
|
/* Write data from the buffer to a file descriptor */
|
689
689
|
static int
|
690
690
|
buffer_write_to(struct buffer * buf, int fd)
|
691
691
|
{
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
692
|
+
int bytes_written, total_bytes_written = 0;
|
693
|
+
struct buffer_node *tmp;
|
694
|
+
|
695
|
+
while (buf->head) {
|
696
|
+
bytes_written = write(fd, buf->head->data + buf->head->start, buf->head->end - buf->head->start);
|
697
|
+
|
698
|
+
/* If the write failed... */
|
699
|
+
if (bytes_written < 0) {
|
700
|
+
if (errno != EAGAIN)
|
701
|
+
rb_sys_fail("write");
|
702
|
+
|
703
|
+
return total_bytes_written;
|
704
|
+
}
|
705
|
+
|
706
|
+
total_bytes_written += bytes_written;
|
707
|
+
buf->size -= bytes_written;
|
708
|
+
|
709
|
+
/* If the write blocked... */
|
710
|
+
if (bytes_written < buf->head->end - buf->head->start) {
|
711
|
+
buf->head->start += bytes_written;
|
712
|
+
return total_bytes_written;
|
713
|
+
}
|
714
|
+
/* Otherwise we wrote the whole buffer */
|
715
|
+
tmp = buf->head;
|
716
|
+
buf->head = tmp->next;
|
717
|
+
buffer_node_free(buf, tmp);
|
718
|
+
|
719
|
+
if (!buf->head)
|
720
|
+
buf->tail = 0;
|
721
|
+
}
|
722
|
+
|
723
|
+
return total_bytes_written;
|
724
724
|
}
|
725
725
|
|
726
726
|
/* Read data from a file descriptor to a buffer */
|
@@ -728,37 +728,38 @@ buffer_write_to(struct buffer * buf, int fd)
|
|
728
728
|
static int
|
729
729
|
buffer_read_from(struct buffer * buf, int fd)
|
730
730
|
{
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
731
|
+
int bytes_read, total_bytes_read = 0;
|
732
|
+
unsigned nbytes;
|
733
|
+
|
734
|
+
/* Empty list needs initialized */
|
735
|
+
if (!buf->head) {
|
736
|
+
buf->head = buffer_node_new(buf);
|
737
|
+
buf->tail = buf->head;
|
738
|
+
}
|
739
|
+
|
740
|
+
do {
|
741
|
+
nbytes = buf->node_size - buf->tail->end;
|
742
|
+
bytes_read = read(fd, buf->tail->data + buf->tail->end, nbytes);
|
743
|
+
|
744
|
+
if (bytes_read == 0) {
|
745
|
+
return -1;
|
746
|
+
//When the file reaches EOF
|
747
|
+
} else if (bytes_read < 0) {
|
748
|
+
if (errno != EAGAIN)
|
749
|
+
rb_sys_fail("read");
|
750
|
+
|
751
|
+
return total_bytes_read;
|
752
|
+
}
|
753
|
+
|
754
|
+
total_bytes_read += bytes_read;
|
755
|
+
buf->tail->end += bytes_read;
|
756
|
+
buf->size += bytes_read;
|
757
|
+
|
758
|
+
if (buf->tail->end == buf->node_size) {
|
759
|
+
buf->tail->next = buffer_node_new(buf);
|
760
|
+
buf->tail = buf->tail->next;
|
761
|
+
}
|
762
|
+
} while (bytes_read == nbytes);
|
763
|
+
|
764
|
+
return total_bytes_read;
|
764
765
|
}
|
data/lib/iobuffer/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: iobuffer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-02-
|
12
|
+
date: 2012-02-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake-compiler
|
16
|
-
requirement: &
|
16
|
+
requirement: &70270228214060 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70270228214060
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rake
|
27
|
-
requirement: &
|
27
|
+
requirement: &70270228213600 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70270228213600
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: rspec
|
38
|
-
requirement: &
|
38
|
+
requirement: &70270228213180 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,7 +43,7 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70270228213180
|
47
47
|
description: fast buffers for non-blocking IO
|
48
48
|
email:
|
49
49
|
- tony.arcieri@gmail.com
|
@@ -55,7 +55,6 @@ files:
|
|
55
55
|
- README.md
|
56
56
|
- lib/iobuffer/version.rb
|
57
57
|
- lib/iobuffer.rb
|
58
|
-
- lib/iobuffer_ext.bundle
|
59
58
|
- ext/iobuffer.c
|
60
59
|
- ext/extconf.rb
|
61
60
|
homepage: https://github.com/tarcieri/iobuffer
|
data/lib/iobuffer_ext.bundle
DELETED
Binary file
|