iobuffer 1.0.0 → 1.1.0

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/iobuffer.c CHANGED
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (C) 2007-08 Tony Arcieri
2
+ * Copyright (C) 2007-12 Tony Arcieri
3
3
  * You may redistribute this under the terms of the MIT license.
4
4
  * See LICENSE for details
5
5
  */
@@ -14,6 +14,9 @@
14
14
  #include <unistd.h>
15
15
  #include <errno.h>
16
16
 
17
+ /* 1 GiB maximum buffer size */
18
+ #define MAX_BUFFER_SIZE 0x40000000
19
+
17
20
  /* Macro for retrieving the file descriptor from an FPTR */
18
21
  #if !HAVE_RB_IO_T_FD
19
22
  #define FPTR_TO_FD(fptr) fileno(fptr->f)
@@ -26,93 +29,102 @@
26
29
  static unsigned default_node_size = DEFAULT_NODE_SIZE;
27
30
 
28
31
  struct buffer {
29
- unsigned size, node_size;
30
- struct buffer_node *head, *tail;
31
- struct buffer_node *pool_head, *pool_tail;
32
-
32
+ unsigned size, node_size;
33
+ struct buffer_node *head, *tail;
34
+ struct buffer_node *pool_head, *pool_tail;
35
+
33
36
  };
34
37
 
35
38
  struct buffer_node {
36
- unsigned start, end;
37
- struct buffer_node *next;
38
- unsigned char data[0];
39
+ unsigned start, end;
40
+ struct buffer_node *next;
41
+ unsigned char data[0];
39
42
  };
40
43
 
41
- static VALUE cIO_Buffer = Qnil;
42
-
43
- static VALUE IO_Buffer_allocate(VALUE klass);
44
- static void IO_Buffer_mark(struct buffer *);
45
- static void IO_Buffer_free(struct buffer *);
46
-
47
- static VALUE IO_Buffer_default_node_size(VALUE klass);
48
- static VALUE IO_Buffer_set_default_node_size(VALUE klass, VALUE size);
49
- static VALUE IO_Buffer_initialize(int argc, VALUE *argv, VALUE self);
50
- static VALUE IO_Buffer_clear(VALUE self);
51
- static VALUE IO_Buffer_size(VALUE self);
52
- static VALUE IO_Buffer_empty(VALUE self);
53
- static VALUE IO_Buffer_append(VALUE self, VALUE data);
54
- static VALUE IO_Buffer_prepend(VALUE self, VALUE data);
55
- static VALUE IO_Buffer_read(int argc, VALUE *argv, VALUE self);
56
- static VALUE IO_Buffer_to_str(VALUE self);
57
- static VALUE IO_Buffer_read_from(VALUE self, VALUE io);
58
- static VALUE IO_Buffer_write_to(VALUE self, VALUE io);
44
+ static VALUE cIO_Buffer = Qnil;
45
+
46
+ static VALUE IO_Buffer_allocate(VALUE klass);
47
+ static void IO_Buffer_mark(struct buffer *);
48
+ static void IO_Buffer_free(struct buffer *);
49
+
50
+ static VALUE IO_Buffer_default_node_size(VALUE klass);
51
+ static VALUE IO_Buffer_set_default_node_size(VALUE klass, VALUE size);
52
+ static VALUE IO_Buffer_initialize(int argc, VALUE * argv, VALUE self);
53
+ static VALUE IO_Buffer_clear(VALUE self);
54
+ static VALUE IO_Buffer_size(VALUE self);
55
+ static VALUE IO_Buffer_empty(VALUE self);
56
+ static VALUE IO_Buffer_append(VALUE self, VALUE data);
57
+ static VALUE IO_Buffer_prepend(VALUE self, VALUE data);
58
+ static VALUE IO_Buffer_read(int argc, VALUE * argv, VALUE self);
59
+ static VALUE IO_Buffer_read_frame(VALUE self, VALUE data, VALUE mark);
60
+ static VALUE IO_Buffer_to_str(VALUE self);
61
+ static VALUE IO_Buffer_read_from(VALUE self, VALUE io);
62
+ static VALUE IO_Buffer_write_to(VALUE self, VALUE io);
59
63
 
60
64
  static struct buffer *buffer_new(void);
61
- static void buffer_clear(struct buffer *buf);
62
- static void buffer_free(struct buffer *buf);
63
- static void buffer_free_pool(struct buffer *buf);
64
- static void buffer_prepend(struct buffer *buf, char *str, unsigned len);
65
- static void buffer_append(struct buffer *buf, char *str, unsigned len);
66
- static void buffer_read(struct buffer *buf, char *str, unsigned len);
67
- static void buffer_copy(struct buffer *buf, char *str, unsigned len);
68
- static int buffer_read_from(struct buffer *buf, int fd);
69
- static int buffer_write_to(struct buffer *buf, int fd);
70
-
71
- /*
65
+ static void buffer_clear(struct buffer * buf);
66
+ static void buffer_free(struct buffer * buf);
67
+ static void buffer_free_pool(struct buffer * buf);
68
+ static void buffer_prepend(struct buffer * buf, char *str, unsigned len);
69
+ static void buffer_append(struct buffer * buf, char *str, unsigned len);
70
+ static void buffer_read(struct buffer * buf, char *str, unsigned len);
71
+ static int buffer_read_frame(struct buffer * buf, VALUE str, char frame_mark);
72
+ static void buffer_copy(struct buffer * buf, char *str, unsigned len);
73
+ static int buffer_read_from(struct buffer * buf, int fd);
74
+ static int buffer_write_to(struct buffer * buf, int fd);
75
+
76
+ /*
72
77
  * High-performance I/O buffer intended for use in non-blocking programs
73
78
  *
74
- * Data is stored in as a memory-pooled linked list of equally sized
75
- * chunks. Routines are provided for high speed non-blocking reads
76
- * and writes from Ruby IO objects.
79
+ * Data is stored in as a memory-pooled linked list of equally sized chunks.
80
+ * Routines are provided for high speed non-blocking reads and writes from
81
+ * Ruby IO objects.
77
82
  */
78
- void Init_iobuffer()
83
+ void
84
+ Init_iobuffer()
79
85
  {
80
- cIO_Buffer = rb_define_class_under(rb_cIO, "Buffer", rb_cObject);
81
- rb_define_alloc_func(cIO_Buffer, IO_Buffer_allocate);
82
-
83
- rb_define_singleton_method(cIO_Buffer, "default_node_size",
84
- IO_Buffer_default_node_size, 0);
85
- rb_define_singleton_method(cIO_Buffer, "default_node_size=",
86
- IO_Buffer_set_default_node_size, 1);
87
-
88
- rb_define_method(cIO_Buffer, "initialize", IO_Buffer_initialize, -1);
89
- rb_define_method(cIO_Buffer, "clear", IO_Buffer_clear, 0);
90
- rb_define_method(cIO_Buffer, "size", IO_Buffer_size, 0);
91
- rb_define_method(cIO_Buffer, "empty?", IO_Buffer_empty, 0);
92
- rb_define_method(cIO_Buffer, "<<", IO_Buffer_append, 1);
93
- rb_define_method(cIO_Buffer, "append", IO_Buffer_append, 1);
94
- rb_define_method(cIO_Buffer, "write", IO_Buffer_append, 1);
95
- rb_define_method(cIO_Buffer, "prepend", IO_Buffer_prepend, 1);
96
- rb_define_method(cIO_Buffer, "read", IO_Buffer_read, -1);
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);
97
104
  rb_define_method(cIO_Buffer, "to_str", IO_Buffer_to_str, 0);
98
105
  rb_define_method(cIO_Buffer, "read_from", IO_Buffer_read_from, 1);
99
- rb_define_method(cIO_Buffer, "write_to", IO_Buffer_write_to, 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));
100
109
  }
101
110
 
102
- static VALUE IO_Buffer_allocate(VALUE klass)
111
+ static VALUE
112
+ IO_Buffer_allocate(VALUE klass)
103
113
  {
104
- return Data_Wrap_Struct(klass, IO_Buffer_mark, IO_Buffer_free, buffer_new());
114
+ return Data_Wrap_Struct(klass, IO_Buffer_mark, IO_Buffer_free, buffer_new());
105
115
  }
106
116
 
107
- static void IO_Buffer_mark(struct buffer *buf)
117
+ static void
118
+ IO_Buffer_mark(struct buffer * buf)
108
119
  {
109
- /* Naively discard the memory pool whenever Ruby garbage collects */
110
- buffer_free_pool(buf);
120
+ /* Naively discard the memory pool whenever Ruby garbage collects */
121
+ buffer_free_pool(buf);
111
122
  }
112
123
 
113
- static void IO_Buffer_free(struct buffer *buf)
124
+ static void
125
+ IO_Buffer_free(struct buffer * buf)
114
126
  {
115
- buffer_free(buf);
127
+ buffer_free(buf);
116
128
  }
117
129
 
118
130
  /**
@@ -121,22 +133,26 @@ static void IO_Buffer_free(struct buffer *buf)
121
133
  *
122
134
  * Retrieves the current value of the default node size.
123
135
  */
124
- static VALUE IO_Buffer_default_node_size(VALUE klass)
136
+ static VALUE
137
+ IO_Buffer_default_node_size(VALUE klass)
125
138
  {
126
- return UINT2NUM(default_node_size);
139
+ return UINT2NUM(default_node_size);
127
140
  }
128
141
 
129
142
  /*
130
143
  * safely converts node sizes from Ruby numerics to C and raising
131
144
  * ArgumentError or RangeError on invalid sizes
132
145
  */
133
- static unsigned convert_node_size(VALUE size)
146
+ static unsigned
147
+ convert_node_size(VALUE size)
134
148
  {
135
- int node_size = NUM2INT(size);
136
-
137
- if(node_size < 1) rb_raise(rb_eArgError, "invalid buffer size");
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");
138
154
 
139
- return (unsigned)node_size;
155
+ return (unsigned) NUM2INT(size);
140
156
  }
141
157
 
142
158
  /**
@@ -145,496 +161,604 @@ static unsigned convert_node_size(VALUE size)
145
161
  *
146
162
  * Sets the default node size for calling IO::Buffer.new with no arguments.
147
163
  */
148
- static VALUE IO_Buffer_set_default_node_size(VALUE klass, VALUE size)
164
+ static VALUE
165
+ IO_Buffer_set_default_node_size(VALUE klass, VALUE size)
149
166
  {
150
- default_node_size = convert_node_size(size);
167
+ default_node_size = convert_node_size(size);
151
168
 
152
- return size;
169
+ return size;
153
170
  }
154
171
 
155
172
  /**
156
173
  * call-seq:
157
174
  * IO_Buffer.new(size = IO::Buffer.default_node_size) -> IO_Buffer
158
- *
175
+ *
159
176
  * Create a new IO_Buffer with linked segments of the given size
160
177
  */
161
- static VALUE IO_Buffer_initialize(int argc, VALUE *argv, VALUE self)
178
+ static VALUE
179
+ IO_Buffer_initialize(int argc, VALUE * argv, VALUE self)
162
180
  {
163
- VALUE node_size_obj;
164
- struct buffer *buf;
165
-
166
- if(rb_scan_args(argc, argv, "01", &node_size_obj) == 1) {
167
- Data_Get_Struct(self, struct buffer, buf);
181
+ VALUE node_size_obj;
182
+ struct buffer *buf;
168
183
 
169
- /* Make sure we're not changing the buffer size after data has been allocated */
170
- assert(!buf->head);
171
- assert(!buf->pool_head);
184
+ if (rb_scan_args(argc, argv, "01", &node_size_obj) == 1) {
185
+ Data_Get_Struct(self, struct buffer, buf);
172
186
 
173
- buf->node_size = convert_node_size(node_size_obj);
174
- }
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);
175
193
 
176
- return Qnil;
194
+ buf->node_size = convert_node_size(node_size_obj);
195
+ }
196
+ return Qnil;
177
197
  }
178
198
 
179
199
  /**
180
200
  * call-seq:
181
201
  * IO_Buffer#clear -> nil
182
- *
202
+ *
183
203
  * Clear all data from the IO_Buffer
184
204
  */
185
- static VALUE IO_Buffer_clear(VALUE self)
205
+ static VALUE
206
+ IO_Buffer_clear(VALUE self)
186
207
  {
187
- struct buffer *buf;
188
- Data_Get_Struct(self, struct buffer, buf);
208
+ struct buffer *buf;
209
+ Data_Get_Struct(self, struct buffer, buf);
189
210
 
190
- buffer_clear(buf);
211
+ buffer_clear(buf);
191
212
 
192
- return Qnil;
213
+ return Qnil;
193
214
  }
194
215
 
195
216
  /**
196
217
  * call-seq:
197
218
  * IO_Buffer#size -> Integer
198
- *
219
+ *
199
220
  * Return the size of the buffer in bytes
200
221
  */
201
- static VALUE IO_Buffer_size(VALUE self)
222
+ static VALUE
223
+ IO_Buffer_size(VALUE self)
202
224
  {
203
- struct buffer *buf;
204
- Data_Get_Struct(self, struct buffer, buf);
225
+ struct buffer *buf;
226
+ Data_Get_Struct(self, struct buffer, buf);
205
227
 
206
- return INT2NUM(buf->size);
228
+ return INT2NUM(buf->size);
207
229
  }
208
230
 
209
231
  /**
210
232
  * call-seq:
211
233
  * IO_Buffer#empty? -> Boolean
212
- *
234
+ *
213
235
  * Is the buffer empty?
214
236
  */
215
- static VALUE IO_Buffer_empty(VALUE self)
237
+ static VALUE
238
+ IO_Buffer_empty(VALUE self)
216
239
  {
217
- struct buffer *buf;
218
- Data_Get_Struct(self, struct buffer, buf);
240
+ struct buffer *buf;
241
+ Data_Get_Struct(self, struct buffer, buf);
219
242
 
220
- return buf->size > 0 ? Qfalse : Qtrue;
243
+ return buf->size > 0 ? Qfalse : Qtrue;
221
244
  }
222
245
 
223
246
  /**
224
247
  * call-seq:
225
248
  * IO_Buffer#append(data) -> String
226
- *
249
+ *
227
250
  * Append the given data to the end of the buffer
228
251
  */
229
- static VALUE IO_Buffer_append(VALUE self, VALUE data)
252
+ static VALUE
253
+ IO_Buffer_append(VALUE self, VALUE data)
230
254
  {
231
- struct buffer *buf;
232
- Data_Get_Struct(self, struct buffer, buf);
255
+ struct buffer *buf;
256
+ Data_Get_Struct(self, struct buffer, buf);
233
257
 
234
- /* Is this needed? Never seen anyone else do it... */
235
- data = rb_convert_type(data, T_STRING, "String", "to_str");
236
- buffer_append(buf, RSTRING_PTR(data), RSTRING_LEN(data));
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));
237
261
 
238
- return data;
262
+ return data;
239
263
  }
240
264
 
241
265
  /**
242
266
  * call-seq:
243
267
  * IO_Buffer#prepend(data) -> String
244
- *
268
+ *
245
269
  * Prepend the given data to the beginning of the buffer
246
270
  */
247
- static VALUE IO_Buffer_prepend(VALUE self, VALUE data)
271
+ static VALUE
272
+ IO_Buffer_prepend(VALUE self, VALUE data)
248
273
  {
249
- struct buffer *buf;
250
- Data_Get_Struct(self, struct buffer, buf);
274
+ struct buffer *buf;
275
+ Data_Get_Struct(self, struct buffer, buf);
251
276
 
252
- data = rb_convert_type(data, T_STRING, "String", "to_str");
253
- buffer_prepend(buf, RSTRING_PTR(data), RSTRING_LEN(data));
277
+ data = rb_convert_type(data, T_STRING, "String", "to_str");
278
+ buffer_prepend(buf, RSTRING_PTR(data), RSTRING_LEN(data));
254
279
 
255
- return data;
280
+ return data;
256
281
  }
257
282
 
258
283
  /**
259
284
  * call-seq:
260
285
  * IO_Buffer#read(length = nil) -> String
261
- *
286
+ *
262
287
  * Read the specified abount of data from the buffer. If no value
263
288
  * is given the entire contents of the buffer are returned. Any data
264
289
  * read from the buffer is cleared.
265
290
  */
266
- static VALUE IO_Buffer_read(int argc, VALUE *argv, VALUE self)
291
+ static VALUE
292
+ IO_Buffer_read(int argc, VALUE * argv, VALUE self)
267
293
  {
268
- VALUE length_obj, str;
269
- int length;
270
- struct buffer *buf;
294
+ VALUE length_obj, str;
295
+ int length;
296
+ struct buffer *buf;
297
+
298
+ Data_Get_Struct(self, struct buffer, buf);
299
+
300
+ if (rb_scan_args(argc, argv, "01", &length_obj) == 1) {
301
+ length = NUM2INT(length_obj);
302
+ } else {
303
+ if (buf->size == 0)
304
+ return rb_str_new2("");
271
305
 
272
- Data_Get_Struct(self, struct buffer, buf);
306
+ length = buf->size;
307
+ }
273
308
 
274
- if(rb_scan_args(argc, argv, "01", &length_obj) == 1) {
275
- length = NUM2INT(length_obj);
276
- } else {
277
- if(buf->size == 0)
278
- return rb_str_new2("");
309
+ if (length > buf->size)
310
+ length = buf->size;
279
311
 
280
- length = buf->size;
281
- }
312
+ if (length < 1)
313
+ rb_raise(rb_eArgError, "length must be greater than zero");
282
314
 
283
- if(length > buf->size)
284
- length = buf->size;
315
+ str = rb_str_new(0, length);
316
+ buffer_read(buf, RSTRING_PTR(str), length);
285
317
 
286
- if(length < 1)
287
- rb_raise(rb_eArgError, "length must be greater than zero");
318
+ return str;
319
+ }
320
+
321
+ /**
322
+ * call-seq:
323
+ * IO_Buffer#read_frame(str, mark) -> boolean
324
+ *
325
+ * Read up to and including the given frame marker (expressed a a
326
+ * Fixnum 0-255) byte, copying into the supplied string object. If the mark is
327
+ * not encountered before the end of the buffer, false is returned but data
328
+ * is still copied into str. True is returned if the end of a frame is reached.
329
+ *
330
+ */
331
+ static VALUE
332
+ IO_Buffer_read_frame(VALUE self, VALUE data, VALUE mark)
333
+ {
334
+ char mark_c = (char) NUM2INT(mark);
335
+ struct buffer *buf;
288
336
 
289
- str = rb_str_new(0, length);
290
- buffer_read(buf, RSTRING_PTR(str), length);
337
+ Data_Get_Struct(self, struct buffer, buf);
291
338
 
292
- return str;
339
+ if (buffer_read_frame(buf, data, mark_c)) {
340
+ return Qtrue;
341
+ } else {
342
+ return Qfalse;
343
+ }
293
344
  }
294
345
 
295
346
  /**
296
347
  * call-seq:
297
348
  * IO_Buffer#to_str -> String
298
- *
349
+ *
299
350
  * Convert the Buffer to a String. The original buffer is unmodified.
300
351
  */
301
- static VALUE IO_Buffer_to_str(VALUE self) {
302
- VALUE str;
352
+ static VALUE
353
+ IO_Buffer_to_str(VALUE self)
354
+ {
355
+ VALUE str;
303
356
  struct buffer *buf;
304
-
357
+
305
358
  Data_Get_Struct(self, struct buffer, buf);
306
-
359
+
307
360
  str = rb_str_new(0, buf->size);
308
361
  buffer_copy(buf, RSTRING_PTR(str), buf->size);
309
-
310
- return str;
362
+
363
+ return str;
311
364
  }
312
365
 
313
366
  /**
314
367
  * call-seq:
315
368
  * IO_Buffer#read_from(io) -> Integer
316
- *
369
+ *
317
370
  * Perform a nonblocking read of the the given IO object and fill
318
371
  * the buffer with any data received. The call will read as much
319
372
  * data as it can until the read would block.
320
373
  */
321
- static VALUE IO_Buffer_read_from(VALUE self, VALUE io) {
322
- struct buffer *buf;
374
+ static VALUE
375
+ IO_Buffer_read_from(VALUE self, VALUE io)
376
+ {
377
+ struct buffer *buf;
378
+ int ret;
323
379
  #if HAVE_RB_IO_T
324
- rb_io_t *fptr;
380
+ rb_io_t *fptr;
325
381
  #else
326
- OpenFile *fptr;
382
+ OpenFile *fptr;
327
383
  #endif
328
384
 
329
- Data_Get_Struct(self, struct buffer, buf);
330
- GetOpenFile(rb_convert_type(io, T_FILE, "IO", "to_io"), fptr);
331
- rb_io_set_nonblock(fptr);
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);
332
388
 
333
- return INT2NUM(buffer_read_from(buf, FPTR_TO_FD(fptr)));
389
+ ret = buffer_read_from(buf, FPTR_TO_FD(fptr));
390
+ return ret == -1 ? Qnil : INT2NUM(ret);
334
391
  }
335
392
 
336
393
  /**
337
394
  * call-seq:
338
395
  * IO_Buffer#write_to(io) -> Integer
339
- *
396
+ *
340
397
  * Perform a nonblocking write of the buffer to the given IO object.
341
398
  * As much data as possible is written until the call would block.
342
399
  * Any data which is written is removed from the buffer.
343
400
  */
344
- static VALUE IO_Buffer_write_to(VALUE self, VALUE io) {
345
- struct buffer *buf;
346
- #if HAVE_RB_IO_T
347
- rb_io_t *fptr;
401
+ static VALUE
402
+ IO_Buffer_write_to(VALUE self, VALUE io)
403
+ {
404
+ struct buffer *buf;
405
+ #if HAVE_RB_IO_T
406
+ rb_io_t *fptr;
348
407
  #else
349
- OpenFile *fptr;
408
+ OpenFile *fptr;
350
409
  #endif
351
410
 
352
- Data_Get_Struct(self, struct buffer, buf);
353
- GetOpenFile(rb_convert_type(io, T_FILE, "IO", "to_io"), fptr);
354
- rb_io_set_nonblock(fptr);
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);
355
414
 
356
- return INT2NUM(buffer_write_to(buf, FPTR_TO_FD(fptr)));
415
+ return INT2NUM(buffer_write_to(buf, FPTR_TO_FD(fptr)));
357
416
  }
358
417
 
359
418
  /*
360
- * Ruby bindings end here. Below is the actual implementation of
419
+ * Ruby bindings end here. Below is the actual implementation of
361
420
  * the underlying byte queue ADT
362
421
  */
363
422
 
364
423
  /* Create a new buffer */
365
- static struct buffer *buffer_new(void)
424
+ static struct buffer *
425
+ buffer_new(void)
366
426
  {
367
- struct buffer *buf;
368
-
369
- buf = (struct buffer *)xmalloc(sizeof(struct buffer));
370
- buf->head = buf->tail = buf->pool_head = buf->pool_tail = 0;
371
- buf->size = 0;
372
- buf->node_size = default_node_size;
373
-
374
- return buf;
427
+ struct buffer *buf;
428
+
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
+
434
+ return buf;
375
435
  }
376
436
 
377
437
  /* Clear all data from a buffer */
378
- static void buffer_clear(struct buffer *buf)
438
+ static void
439
+ buffer_clear(struct buffer * buf)
379
440
  {
380
- /* Move everything into the buffer pool */
381
- if(!buf->pool_tail)
382
- buf->pool_head = buf->pool_tail = buf->head;
383
- else
384
- buf->pool_tail->next = buf->head;
385
-
386
- buf->head = buf->tail = 0;
387
- buf->size = 0;
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;
388
450
  }
389
451
 
390
452
  /* Free a buffer */
391
- static void buffer_free(struct buffer *buf)
453
+ static void
454
+ buffer_free(struct buffer * buf)
392
455
  {
393
- buffer_clear(buf);
394
- buffer_free_pool(buf);
456
+ buffer_clear(buf);
457
+ buffer_free_pool(buf);
395
458
 
396
- free(buf);
459
+ free(buf);
397
460
  }
398
461
 
399
462
  /* Free the memory pool */
400
- static void buffer_free_pool(struct buffer *buf)
463
+ static void
464
+ buffer_free_pool(struct buffer * buf)
401
465
  {
402
- struct buffer_node *tmp;
403
-
404
- while(buf->pool_head) {
405
- tmp = buf->pool_head;
406
- buf->pool_head = tmp->next;
407
- free(tmp);
408
- }
409
-
466
+ struct buffer_node *tmp;
467
+
468
+ while (buf->pool_head) {
469
+ tmp = buf->pool_head;
470
+ buf->pool_head = tmp->next;
471
+ free(tmp);
472
+ }
473
+
410
474
  buf->pool_tail = 0;
411
475
  }
412
476
 
413
477
  /* Create a new buffer_node (or pull one from the memory pool) */
414
- static struct buffer_node *buffer_node_new(struct buffer *buf)
478
+ static struct buffer_node *
479
+ buffer_node_new(struct buffer * buf)
415
480
  {
416
- struct buffer_node *node;
417
-
418
- /* Pull from the memory pool if available */
419
- if(buf->pool_head) {
420
- node = buf->pool_head;
421
- buf->pool_head = node->next;
422
-
423
- if(node->next)
424
- node->next = 0;
425
- else
426
- buf->pool_tail = 0;
427
- } else {
428
- node = (struct buffer_node *)xmalloc(sizeof(struct buffer_node) + buf->node_size);
429
- node->next = 0;
430
- }
431
-
432
- node->start = node->end = 0;
433
- return node;
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;
434
499
  }
435
500
 
436
501
  /* Free a buffer node (i.e. return it to the memory pool) */
437
- static void buffer_node_free(struct buffer *buf, struct buffer_node *node)
502
+ static void
503
+ buffer_node_free(struct buffer * buf, struct buffer_node * node)
438
504
  {
439
- node->next = buf->pool_head;
440
- buf->pool_head = node;
505
+ node->next = buf->pool_head;
506
+ buf->pool_head = node;
441
507
 
442
- if(!buf->pool_tail)
443
- buf->pool_tail = node;
508
+ if (!buf->pool_tail) {
509
+ buf->pool_tail = node;
510
+ }
444
511
  }
445
512
 
446
513
  /* Prepend data to the front of the buffer */
447
- static void buffer_prepend(struct buffer *buf, char *str, unsigned len)
514
+ static void
515
+ buffer_prepend(struct buffer * buf, char *str, unsigned len)
448
516
  {
449
- struct buffer_node *node, *tmp;
450
- buf->size += len;
451
-
452
- /* If it fits in the beginning of the head */
453
- if(buf->head && buf->head->start >= len) {
454
- buf->head->start -= len;
455
- memcpy(buf->head->data + buf->head->start, str, len);
456
- } else {
457
- node = buffer_node_new(buf);
458
- node->next = buf->head;
459
- buf->head = node;
460
- if(!buf->tail) buf->tail = node;
461
-
462
- while(len > buf->node_size) {
463
- memcpy(node->data, str, buf->node_size);
464
- node->end = buf->node_size;
465
-
466
- tmp = buffer_node_new(buf);
467
- tmp->next = node->next;
468
- node->next = tmp;
469
-
470
- if(buf->tail == node) buf->tail = tmp;
471
- node = tmp;
472
-
473
- str += buf->node_size;
474
- len -= buf->node_size;
475
- }
476
-
477
- if(len > 0) {
478
- memcpy(node->data, str, len);
479
- node->end = len;
480
- }
481
- }
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
+ }
482
552
  }
483
553
 
484
554
  /* Append data to the front of the buffer */
485
- static void buffer_append(struct buffer *buf, char *str, unsigned len)
555
+ static void
556
+ buffer_append(struct buffer * buf, char *str, unsigned len)
486
557
  {
487
- unsigned nbytes;
488
- buf->size += len;
489
-
490
- /* If it fits in the remaining space in the tail */
491
- if(buf->tail && len <= buf->node_size - buf->tail->end) {
492
- memcpy(buf->tail->data + buf->tail->end, str, len);
493
- buf->tail->end += len;
494
- return;
495
- }
496
-
497
- /* Empty list needs initialized */
498
- if(!buf->head) {
499
- buf->head = buffer_node_new(buf);
500
- buf->tail = buf->head;
501
- }
502
-
503
- /* Build links out of the data */
504
- while(len > 0) {
505
- nbytes = buf->node_size - buf->tail->end;
506
- if(len < nbytes) nbytes = len;
507
-
508
- memcpy(buf->tail->data + buf->tail->end, str, nbytes);
509
- str += nbytes;
510
- len -= nbytes;
511
-
512
- buf->tail->end += nbytes;
513
-
514
- if(len > 0) {
515
- buf->tail->next = buffer_node_new(buf);
516
- buf->tail = buf->tail->next;
517
- }
518
- }
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
+ }
519
589
  }
520
590
 
521
591
  /* Read data from the buffer (and clear what we've read) */
522
- static void buffer_read(struct buffer *buf, char *str, unsigned len)
592
+ static void
593
+ buffer_read(struct buffer * buf, char *str, unsigned len)
594
+ {
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
+ }
620
+
621
+ /*
622
+ * Read data from the buffer into str until byte frame_mark or empty. Bytes
623
+ * are copied into str and removed if a complete frame is read, a true value
624
+ * is returned
625
+ */
626
+ static int
627
+ buffer_read_frame(struct buffer * buf, VALUE str, char frame_mark)
523
628
  {
524
- unsigned nbytes;
525
- struct buffer_node *tmp;
629
+ unsigned nbytes = 0;
630
+ struct buffer_node *tmp;
631
+
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
+
637
+ loc = memchr(s, frame_mark, nbytes);
638
+
639
+ if (loc) {
640
+ nbytes = loc - s + 1;
641
+ }
642
+
643
+ /* Copy less than everything if we found a frame byte */
644
+ rb_str_cat(str, s, nbytes);
526
645
 
527
- while(buf->size > 0 && len > 0) {
528
- nbytes = buf->head->end - buf->head->start;
529
- if(len < nbytes) nbytes = len;
646
+ /* Fixup the buffer pointers to indicate the bytes were consumed */
647
+ head->start += nbytes;
648
+ buf->size -= nbytes;
530
649
 
531
- memcpy(str, buf->head->data + buf->head->start, nbytes);
532
- str += nbytes;
533
- len -= nbytes;
650
+ if (head->start == head->end) {
651
+ buf->head = head->next;
652
+ buffer_node_free(buf, head);
534
653
 
535
- buf->head->start += nbytes;
536
- buf->size -= nbytes;
654
+ if (!buf->head)
655
+ buf->tail = 0;
656
+ }
537
657
 
538
- if(buf->head->start == buf->head->end) {
539
- tmp = buf->head;
540
- buf->head = tmp->next;
541
- buffer_node_free(buf, tmp);
658
+ if (loc) {
659
+ return 1;
660
+ }
661
+ }
542
662
 
543
- if(!buf->head) buf->tail = 0;
544
- }
545
- }
663
+ return 0;
546
664
  }
547
665
 
548
666
  /* Copy data from the buffer without clearing it */
549
- static void buffer_copy(struct buffer *buf, char *str, unsigned len)
667
+ static void
668
+ buffer_copy(struct buffer * buf, char *str, unsigned len)
550
669
  {
551
- unsigned nbytes;
552
- struct buffer_node *node;
670
+ unsigned nbytes;
671
+ struct buffer_node *node;
553
672
 
554
673
  node = buf->head;
555
- while(node && len > 0) {
556
- nbytes = node->end - node->start;
557
- if(len < nbytes) nbytes = len;
674
+ while (node && len > 0) {
675
+ nbytes = node->end - node->start;
676
+ if (len < nbytes)
677
+ nbytes = len;
558
678
 
559
- memcpy(str, node->data + node->start, nbytes);
560
- str += nbytes;
561
- len -= nbytes;
679
+ memcpy(str, node->data + node->start, nbytes);
680
+ str += nbytes;
681
+ len -= nbytes;
562
682
 
563
- if(node->start + nbytes == node->end)
683
+ if (node->start + nbytes == node->end)
564
684
  node = node->next;
565
- }
685
+ }
566
686
  }
567
687
 
568
688
  /* Write data from the buffer to a file descriptor */
569
- static int buffer_write_to(struct buffer *buf, int fd)
689
+ static int
690
+ buffer_write_to(struct buffer * buf, int fd)
570
691
  {
571
- int bytes_written, total_bytes_written = 0;
572
- struct buffer_node *tmp;
573
-
574
- while(buf->head) {
575
- bytes_written = write(fd, buf->head->data + buf->head->start, buf->head->end - buf->head->start);
692
+ int bytes_written, total_bytes_written = 0;
693
+ struct buffer_node *tmp;
576
694
 
577
- /* If the write failed... */
578
- if(bytes_written < 0) {
579
- if(errno != EAGAIN)
580
- rb_sys_fail("write");
695
+ while (buf->head) {
696
+ bytes_written = write(fd, buf->head->data + buf->head->start, buf->head->end - buf->head->start);
581
697
 
582
- return total_bytes_written;
583
- }
698
+ /* If the write failed... */
699
+ if (bytes_written < 0) {
700
+ if (errno != EAGAIN)
701
+ rb_sys_fail("write");
584
702
 
585
- total_bytes_written += bytes_written;
586
- buf->size -= bytes_written;
703
+ return total_bytes_written;
704
+ }
587
705
 
588
- /* If the write blocked... */
589
- if(bytes_written < buf->head->end - buf->head->start) {
590
- buf->head->start += bytes_written;
591
- return total_bytes_written;
592
- }
706
+ total_bytes_written += bytes_written;
707
+ buf->size -= bytes_written;
593
708
 
594
- /* Otherwise we wrote the whole buffer */
595
- tmp = buf->head;
596
- buf->head = tmp->next;
597
- buffer_node_free(buf, tmp);
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);
598
718
 
599
- if(!buf->head) buf->tail = 0;
600
- }
719
+ if (!buf->head)
720
+ buf->tail = 0;
721
+ }
601
722
 
602
- return total_bytes_written;
723
+ return total_bytes_written;
603
724
  }
604
725
 
605
726
  /* Read data from a file descriptor to a buffer */
606
727
  /* Append data to the front of the buffer */
607
- static int buffer_read_from(struct buffer *buf, int fd)
728
+ static int
729
+ buffer_read_from(struct buffer * buf, int fd)
608
730
  {
609
- int bytes_read, total_bytes_read = 0;
610
- unsigned nbytes;
731
+ int bytes_read, total_bytes_read = 0;
732
+ unsigned nbytes;
611
733
 
612
- /* Empty list needs initialized */
613
- if(!buf->head) {
614
- buf->head = buffer_node_new(buf);
615
- buf->tail = buf->head;
616
- }
734
+ /* Empty list needs initialized */
735
+ if (!buf->head) {
736
+ buf->head = buffer_node_new(buf);
737
+ buf->tail = buf->head;
738
+ }
617
739
 
618
740
  do {
619
- nbytes = buf->node_size - buf->tail->end;
741
+ nbytes = buf->node_size - buf->tail->end;
620
742
  bytes_read = read(fd, buf->tail->data + buf->tail->end, nbytes);
621
-
622
- if(bytes_read < 1) {
623
- if(errno != EAGAIN)
624
- rb_sys_fail("read");
625
-
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
+
626
751
  return total_bytes_read;
627
752
  }
628
-
629
- total_bytes_read += bytes_read;
753
+ total_bytes_read += bytes_read;
630
754
  buf->tail->end += nbytes;
631
755
  buf->size += nbytes;
632
-
633
- if(buf->tail->end == buf->node_size) {
634
- buf->tail->next = buffer_node_new(buf);
635
- buf->tail = buf->tail->next;
756
+
757
+ if (buf->tail->end == buf->node_size) {
758
+ buf->tail->next = buffer_node_new(buf);
759
+ buf->tail = buf->tail->next;
636
760
  }
637
- } while(bytes_read == nbytes);
638
-
761
+ } while (bytes_read == nbytes);
762
+
639
763
  return total_bytes_read;
640
764
  }