iobuffer 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
  }