nio4r 2.0.0.pre → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +0 -1
  3. data/.rubocop.yml +31 -38
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +4 -21
  6. data/CHANGES.md +75 -42
  7. data/Gemfile +11 -3
  8. data/Guardfile +10 -0
  9. data/LICENSE.txt +1 -1
  10. data/README.md +32 -136
  11. data/Rakefile +2 -0
  12. data/examples/echo_server.rb +1 -0
  13. data/ext/libev/Changes +4 -13
  14. data/ext/libev/ev.c +100 -74
  15. data/ext/libev/ev.h +3 -3
  16. data/ext/libev/ev_epoll.c +6 -3
  17. data/ext/libev/ev_kqueue.c +8 -4
  18. data/ext/libev/ev_poll.c +6 -3
  19. data/ext/libev/ev_port.c +8 -4
  20. data/ext/libev/ev_select.c +4 -2
  21. data/ext/nio4r/bytebuffer.c +265 -257
  22. data/ext/nio4r/extconf.rb +2 -10
  23. data/ext/nio4r/monitor.c +93 -46
  24. data/ext/nio4r/nio4r.h +5 -15
  25. data/ext/nio4r/org/nio4r/ByteBuffer.java +193 -209
  26. data/ext/nio4r/org/nio4r/Monitor.java +164 -0
  27. data/ext/nio4r/org/nio4r/Nio4r.java +13 -391
  28. data/ext/nio4r/org/nio4r/Selector.java +278 -0
  29. data/ext/nio4r/selector.c +52 -52
  30. data/lib/nio.rb +3 -3
  31. data/lib/nio/bytebuffer.rb +179 -132
  32. data/lib/nio/monitor.rb +64 -4
  33. data/lib/nio/selector.rb +36 -13
  34. data/lib/nio/version.rb +1 -1
  35. data/nio4r.gemspec +25 -19
  36. data/spec/nio/acceptables_spec.rb +6 -4
  37. data/spec/nio/bytebuffer_spec.rb +323 -51
  38. data/spec/nio/monitor_spec.rb +122 -79
  39. data/spec/nio/selectables/pipe_spec.rb +5 -1
  40. data/spec/nio/selectables/ssl_socket_spec.rb +15 -12
  41. data/spec/nio/selectables/tcp_socket_spec.rb +42 -31
  42. data/spec/nio/selectables/udp_socket_spec.rb +2 -0
  43. data/spec/nio/selector_spec.rb +10 -4
  44. data/spec/spec_helper.rb +24 -3
  45. data/spec/support/selectable_examples.rb +7 -5
  46. data/tasks/extension.rake +2 -0
  47. data/tasks/rspec.rake +2 -0
  48. data/tasks/rubocop.rake +2 -0
  49. metadata +15 -11
  50. data/.rubocop_todo.yml +0 -35
@@ -515,10 +515,10 @@ enum {
515
515
 
516
516
  /* method bits to be ored together */
517
517
  enum {
518
- EVBACKEND_SELECT = 0x00000001U, /* about anywhere */
519
- EVBACKEND_POLL = 0x00000002U, /* !win */
518
+ EVBACKEND_SELECT = 0x00000001U, /* available just about anywhere */
519
+ EVBACKEND_POLL = 0x00000002U, /* !win, !aix, broken on osx */
520
520
  EVBACKEND_EPOLL = 0x00000004U, /* linux */
521
- EVBACKEND_KQUEUE = 0x00000008U, /* bsd */
521
+ EVBACKEND_KQUEUE = 0x00000008U, /* bsd, broken on osx */
522
522
  EVBACKEND_DEVPOLL = 0x00000010U, /* solaris 8 */ /* NYI */
523
523
  EVBACKEND_PORT = 0x00000020U, /* solaris 10 */
524
524
  EVBACKEND_ALL = 0x0000003FU, /* all known backends */
@@ -235,7 +235,8 @@ epoll_poll (EV_P_ ev_tstamp timeout)
235
235
  }
236
236
  }
237
237
 
238
- int inline_size
238
+ inline_size
239
+ int
239
240
  epoll_init (EV_P_ int flags)
240
241
  {
241
242
  #ifdef EPOLL_CLOEXEC
@@ -260,14 +261,16 @@ epoll_init (EV_P_ int flags)
260
261
  return EVBACKEND_EPOLL;
261
262
  }
262
263
 
263
- void inline_size
264
+ inline_size
265
+ void
264
266
  epoll_destroy (EV_P)
265
267
  {
266
268
  ev_free (epoll_events);
267
269
  array_free (epoll_eperm, EMPTY);
268
270
  }
269
271
 
270
- void inline_size
272
+ inline_size
273
+ void
271
274
  epoll_fork (EV_P)
272
275
  {
273
276
  close (backend_fd);
@@ -43,7 +43,8 @@
43
43
  #include <string.h>
44
44
  #include <errno.h>
45
45
 
46
- void inline_speed
46
+ inline_speed
47
+ void
47
48
  kqueue_change (EV_P_ int fd, int filter, int flags, int fflags)
48
49
  {
49
50
  ++kqueue_changecnt;
@@ -152,7 +153,8 @@ kqueue_poll (EV_P_ ev_tstamp timeout)
152
153
  }
153
154
  }
154
155
 
155
- int inline_size
156
+ inline_size
157
+ int
156
158
  kqueue_init (EV_P_ int flags)
157
159
  {
158
160
  /* initialize the kernel queue */
@@ -176,14 +178,16 @@ kqueue_init (EV_P_ int flags)
176
178
  return EVBACKEND_KQUEUE;
177
179
  }
178
180
 
179
- void inline_size
181
+ inline_size
182
+ void
180
183
  kqueue_destroy (EV_P)
181
184
  {
182
185
  ev_free (kqueue_events);
183
186
  ev_free (kqueue_changes);
184
187
  }
185
188
 
186
- void inline_size
189
+ inline_size
190
+ void
187
191
  kqueue_fork (EV_P)
188
192
  {
189
193
  /* some BSD kernels don't just destroy the kqueue itself,
@@ -39,7 +39,8 @@
39
39
 
40
40
  #include <poll.h>
41
41
 
42
- void inline_size
42
+ inline_size
43
+ void
43
44
  pollidx_init (int *base, int count)
44
45
  {
45
46
  /* consider using memset (.., -1, ...), which is practically guaranteed
@@ -126,7 +127,8 @@ poll_poll (EV_P_ ev_tstamp timeout)
126
127
  }
127
128
  }
128
129
 
129
- int inline_size
130
+ inline_size
131
+ int
130
132
  poll_init (EV_P_ int flags)
131
133
  {
132
134
  backend_mintime = 1e-3;
@@ -139,7 +141,8 @@ poll_init (EV_P_ int flags)
139
141
  return EVBACKEND_POLL;
140
142
  }
141
143
 
142
- void inline_size
144
+ inline_size
145
+ void
143
146
  poll_destroy (EV_P)
144
147
  {
145
148
  ev_free (pollidxs);
@@ -55,7 +55,8 @@
55
55
  #include <string.h>
56
56
  #include <errno.h>
57
57
 
58
- void inline_speed
58
+ inline_speed
59
+ void
59
60
  port_associate_and_check (EV_P_ int fd, int ev)
60
61
  {
61
62
  if (0 >
@@ -136,7 +137,8 @@ port_poll (EV_P_ ev_tstamp timeout)
136
137
  }
137
138
  }
138
139
 
139
- int inline_size
140
+ inline_size
141
+ int
140
142
  port_init (EV_P_ int flags)
141
143
  {
142
144
  /* Initialize the kernel queue */
@@ -163,13 +165,15 @@ port_init (EV_P_ int flags)
163
165
  return EVBACKEND_PORT;
164
166
  }
165
167
 
166
- void inline_size
168
+ inline_size
169
+ void
167
170
  port_destroy (EV_P)
168
171
  {
169
172
  ev_free (port_events);
170
173
  }
171
174
 
172
- void inline_size
175
+ inline_size
176
+ void
173
177
  port_fork (EV_P)
174
178
  {
175
179
  close (backend_fd);
@@ -271,7 +271,8 @@ select_poll (EV_P_ ev_tstamp timeout)
271
271
  #endif
272
272
  }
273
273
 
274
- int inline_size
274
+ inline_size
275
+ int
275
276
  select_init (EV_P_ int flags)
276
277
  {
277
278
  backend_mintime = 1e-6;
@@ -300,7 +301,8 @@ select_init (EV_P_ int flags)
300
301
  return EVBACKEND_SELECT;
301
302
  }
302
303
 
303
- void inline_size
304
+ inline_size
305
+ void
304
306
  select_destroy (EV_P)
305
307
  {
306
308
  ev_free (vec_ri);
@@ -2,34 +2,39 @@
2
2
 
3
3
  static VALUE mNIO = Qnil;
4
4
  static VALUE cNIO_ByteBuffer = Qnil;
5
+ static VALUE cNIO_ByteBuffer_OverflowError = Qnil;
6
+ static VALUE cNIO_ByteBuffer_UnderflowError = Qnil;
7
+ static VALUE cNIO_ByteBuffer_MarkUnsetError = Qnil;
5
8
 
6
9
  /* Allocator/deallocator */
7
10
  static VALUE NIO_ByteBuffer_allocate(VALUE klass);
8
- static void NIO_ByteBuffer_mark(struct NIO_ByteBuffer *byteBuffer);
11
+ static void NIO_ByteBuffer_gc_mark(struct NIO_ByteBuffer *byteBuffer);
9
12
  static void NIO_ByteBuffer_free(struct NIO_ByteBuffer *byteBuffer);
10
13
 
11
14
  /* Methods */
12
- static VALUE NIO_ByteBuffer_initialize(VALUE self, VALUE value, VALUE offset, VALUE length);
13
- static VALUE NIO_ByteBuffer_put(VALUE self, VALUE string);
14
- static VALUE NIO_ByteBuffer_get(VALUE self);
15
- static VALUE NIO_ByteBuffer_readnext(VALUE self, VALUE amount);
16
- static VALUE NIO_ByteBuffer_writeTo(VALUE self, VALUE file);
17
- static VALUE NIO_ByteBuffer_readFrom(VALUE self, VALUE file);
15
+ static VALUE NIO_ByteBuffer_initialize(VALUE self, VALUE capacity);
16
+ static VALUE NIO_ByteBuffer_clear(VALUE self);
17
+ static VALUE NIO_ByteBuffer_get_position(VALUE self);
18
+ static VALUE NIO_ByteBuffer_set_position(VALUE self, VALUE new_position);
19
+ static VALUE NIO_ByteBuffer_get_limit(VALUE self);
20
+ static VALUE NIO_ByteBuffer_set_limit(VALUE self, VALUE new_limit);
21
+ static VALUE NIO_ByteBuffer_capacity(VALUE self);
18
22
  static VALUE NIO_ByteBuffer_remaining(VALUE self);
19
- static VALUE NIO_ByteBuffer_hasRemaining(VALUE self);
20
- static VALUE NIO_ByteBuffer_getOffset(VALUE self);
21
- static VALUE NIO_ByteBuffer_equals(VALUE self, VALUE other);
23
+ static VALUE NIO_ByteBuffer_full(VALUE self);
24
+ static VALUE NIO_ByteBuffer_get(int argc, VALUE *argv, VALUE self);
25
+ static VALUE NIO_ByteBuffer_fetch(VALUE self, VALUE index);
26
+ static VALUE NIO_ByteBuffer_put(VALUE self, VALUE string);
27
+ static VALUE NIO_ByteBuffer_write_to(VALUE self, VALUE file);
28
+ static VALUE NIO_ByteBuffer_read_from(VALUE self, VALUE file);
22
29
  static VALUE NIO_ByteBuffer_flip(VALUE self);
23
30
  static VALUE NIO_ByteBuffer_rewind(VALUE self);
31
+ static VALUE NIO_ByteBuffer_mark(VALUE self);
24
32
  static VALUE NIO_ByteBuffer_reset(VALUE self);
25
- static VALUE NIO_ByteBuffer_markBuffer(VALUE self);
26
- static VALUE NIO_ByteBuffer_clear(VALUE self);
27
33
  static VALUE NIO_ByteBuffer_compact(VALUE self);
28
- static VALUE NIO_ByteBuffer_capacity(VALUE self);
29
- static VALUE NIO_ByteBuffer_position(VALUE self, VALUE newPosition);
30
- static VALUE NIO_ByteBuffer_setLimit(VALUE self, VALUE newLimit);
31
- static VALUE NIO_ByteBuffer_getLimit(VALUE self);
32
- static VALUE NIO_ByteBuffer_toString(VALUE self);
34
+ static VALUE NIO_ByteBuffer_each(VALUE self);
35
+ static VALUE NIO_ByteBuffer_inspect(VALUE self);
36
+
37
+ #define MARK_UNSET -1
33
38
 
34
39
  void Init_NIO_ByteBuffer()
35
40
  {
@@ -37,36 +42,43 @@ void Init_NIO_ByteBuffer()
37
42
  cNIO_ByteBuffer = rb_define_class_under(mNIO, "ByteBuffer", rb_cObject);
38
43
  rb_define_alloc_func(cNIO_ByteBuffer, NIO_ByteBuffer_allocate);
39
44
 
40
- rb_define_method(cNIO_ByteBuffer, "initialize", NIO_ByteBuffer_initialize, 3);
41
- rb_define_method(cNIO_ByteBuffer, "<<", NIO_ByteBuffer_put, 1);
42
- rb_define_method(cNIO_ByteBuffer, "get", NIO_ByteBuffer_get, 0);
43
- rb_define_method(cNIO_ByteBuffer, "read_next", NIO_ByteBuffer_readnext, 1);
44
- rb_define_method(cNIO_ByteBuffer, "write_to", NIO_ByteBuffer_writeTo, 1);
45
- rb_define_method(cNIO_ByteBuffer, "read_from", NIO_ByteBuffer_readFrom, 1);
45
+ cNIO_ByteBuffer_OverflowError = rb_define_class_under(cNIO_ByteBuffer, "OverflowError", rb_eIOError);
46
+ cNIO_ByteBuffer_UnderflowError = rb_define_class_under(cNIO_ByteBuffer, "UnderflowError", rb_eIOError);
47
+ cNIO_ByteBuffer_MarkUnsetError = rb_define_class_under(cNIO_ByteBuffer, "MarkUnsetError", rb_eIOError);
48
+
49
+ rb_include_module(cNIO_ByteBuffer, rb_mEnumerable);
50
+
51
+ rb_define_method(cNIO_ByteBuffer, "initialize", NIO_ByteBuffer_initialize, 1);
52
+ rb_define_method(cNIO_ByteBuffer, "clear", NIO_ByteBuffer_clear, 0);
53
+ rb_define_method(cNIO_ByteBuffer, "position", NIO_ByteBuffer_get_position, 0);
54
+ rb_define_method(cNIO_ByteBuffer, "position=", NIO_ByteBuffer_set_position, 1);
55
+ rb_define_method(cNIO_ByteBuffer, "limit", NIO_ByteBuffer_get_limit, 0);
56
+ rb_define_method(cNIO_ByteBuffer, "limit=", NIO_ByteBuffer_set_limit, 1);
57
+ rb_define_method(cNIO_ByteBuffer, "capacity", NIO_ByteBuffer_capacity, 0);
58
+ rb_define_method(cNIO_ByteBuffer, "size", NIO_ByteBuffer_capacity, 0);
46
59
  rb_define_method(cNIO_ByteBuffer, "remaining", NIO_ByteBuffer_remaining, 0);
47
- rb_define_method(cNIO_ByteBuffer, "remaining?", NIO_ByteBuffer_hasRemaining, 0);
48
- rb_define_method(cNIO_ByteBuffer, "offset?", NIO_ByteBuffer_getOffset, 0);
49
- rb_define_method(cNIO_ByteBuffer, "equals", NIO_ByteBuffer_equals, 1);
60
+ rb_define_method(cNIO_ByteBuffer, "full?", NIO_ByteBuffer_full, 0);
61
+ rb_define_method(cNIO_ByteBuffer, "get", NIO_ByteBuffer_get, -1);
62
+ rb_define_method(cNIO_ByteBuffer, "[]", NIO_ByteBuffer_fetch, 1);
63
+ rb_define_method(cNIO_ByteBuffer, "<<", NIO_ByteBuffer_put, 1);
64
+ rb_define_method(cNIO_ByteBuffer, "read_from", NIO_ByteBuffer_read_from, 1);
65
+ rb_define_method(cNIO_ByteBuffer, "write_to", NIO_ByteBuffer_write_to, 1);
50
66
  rb_define_method(cNIO_ByteBuffer, "flip", NIO_ByteBuffer_flip, 0);
51
67
  rb_define_method(cNIO_ByteBuffer, "rewind", NIO_ByteBuffer_rewind, 0);
68
+ rb_define_method(cNIO_ByteBuffer, "mark", NIO_ByteBuffer_mark, 0);
52
69
  rb_define_method(cNIO_ByteBuffer, "reset", NIO_ByteBuffer_reset, 0);
53
- rb_define_method(cNIO_ByteBuffer, "mark", NIO_ByteBuffer_markBuffer, 0);
54
- rb_define_method(cNIO_ByteBuffer, "clear", NIO_ByteBuffer_clear, 0);
55
70
  rb_define_method(cNIO_ByteBuffer, "compact", NIO_ByteBuffer_compact, 0);
56
- rb_define_method(cNIO_ByteBuffer, "capacity", NIO_ByteBuffer_capacity, 0);
57
- rb_define_method(cNIO_ByteBuffer, "position", NIO_ByteBuffer_position, 1);
58
- rb_define_method(cNIO_ByteBuffer, "limit", NIO_ByteBuffer_setLimit, 1);
59
- rb_define_method(cNIO_ByteBuffer, "limit?", NIO_ByteBuffer_getLimit, 0);
60
- rb_define_method(cNIO_ByteBuffer, "to_s", NIO_ByteBuffer_toString, 0);
71
+ rb_define_method(cNIO_ByteBuffer, "each", NIO_ByteBuffer_each, 0);
72
+ rb_define_method(cNIO_ByteBuffer, "inspect", NIO_ByteBuffer_inspect, 0);
61
73
  }
62
74
 
63
75
  static VALUE NIO_ByteBuffer_allocate(VALUE klass)
64
76
  {
65
77
  struct NIO_ByteBuffer *bytebuffer = (struct NIO_ByteBuffer *)xmalloc(sizeof(struct NIO_ByteBuffer));
66
- return Data_Wrap_Struct(klass, NIO_ByteBuffer_mark, NIO_ByteBuffer_free, bytebuffer);
78
+ return Data_Wrap_Struct(klass, NIO_ByteBuffer_gc_mark, NIO_ByteBuffer_free, bytebuffer);
67
79
  }
68
80
 
69
- static void NIO_ByteBuffer_mark(struct NIO_ByteBuffer *buffer)
81
+ static void NIO_ByteBuffer_gc_mark(struct NIO_ByteBuffer *buffer)
70
82
  {
71
83
  }
72
84
 
@@ -75,339 +87,335 @@ static void NIO_ByteBuffer_free(struct NIO_ByteBuffer *buffer)
75
87
  xfree(buffer);
76
88
  }
77
89
 
78
- static VALUE NIO_ByteBuffer_initialize(VALUE self, VALUE value, VALUE i_offset, VALUE i_length)
90
+ static VALUE NIO_ByteBuffer_initialize(VALUE self, VALUE capacity)
79
91
  {
80
- //Value can be either.
81
- //NUM -> Size of the buffer
82
- //STRING -> Data to be stored on the buffer
83
- struct NIO_ByteBuffer *byteBuffer;
84
- Data_Get_Struct(self, struct NIO_ByteBuffer, byteBuffer);
85
-
86
- switch (TYPE(value)) {
87
- case T_FIXNUM:
88
- byteBuffer->size = NUM2INT(value);
89
- byteBuffer->buffer = malloc(sizeof(char) * byteBuffer->size);
90
- break;
91
- case T_STRING:
92
- byteBuffer->size = RSTRING_LEN(value);
93
- byteBuffer->buffer = StringValuePtr(value);
94
- //buffer = RSTRING_PTR(str);
95
- break;
96
- default:
97
- /* raise exception */
98
- rb_raise(rb_eTypeError, "not a valid input");
99
- break;
100
- }
101
-
102
- byteBuffer->position = 0;
103
- byteBuffer->offset = 0;
104
- byteBuffer->limit = byteBuffer->size - 1;
105
- byteBuffer->self = self;
92
+ struct NIO_ByteBuffer *buffer;
93
+ Data_Get_Struct(self, struct NIO_ByteBuffer, buffer);
106
94
 
107
- if(i_offset != Qnil && TYPE(i_offset) == T_FIXNUM) {
108
- byteBuffer->offset = NUM2INT(i_offset);
109
- byteBuffer->position = byteBuffer->offset;
95
+ buffer->capacity = NUM2INT(capacity);
96
+ buffer->buffer = xmalloc(buffer->capacity);
110
97
 
111
- if(i_length != Qnil && TYPE(i_length) == T_FIXNUM) {
112
- int length = NUM2INT(i_length);
113
-
114
- if(byteBuffer->offset + length < byteBuffer->size) {
115
- byteBuffer->limit = byteBuffer->offset + length;
116
- } else {
117
- rb_raise(rb_eRuntimeError, "Invalid Arguiments Exception");
118
- }
119
- }
120
- }
121
-
122
- if(byteBuffer->size == 0) {
123
- rb_raise(rb_eRuntimeError, "Invalid Arguiments Exception");
124
- }
98
+ NIO_ByteBuffer_clear(self);
125
99
 
126
100
  return self;
127
101
  }
128
102
 
129
- static VALUE NIO_ByteBuffer_put(VALUE self, VALUE string)
103
+ static VALUE NIO_ByteBuffer_clear(VALUE self)
130
104
  {
131
- struct NIO_ByteBuffer *byteBuffer;
132
- Data_Get_Struct(self, struct NIO_ByteBuffer, byteBuffer);
105
+ struct NIO_ByteBuffer *buffer;
106
+ Data_Get_Struct(self, struct NIO_ByteBuffer, buffer);
133
107
 
134
- if(TYPE(string) == T_STRING) {
135
- char *temp = StringValuePtr(string);
136
- int i = 0;
137
- int limit = RSTRING_LEN(string);
108
+ memset(buffer->buffer, 0, buffer->capacity);
138
109
 
139
- for(byteBuffer->position; i < limit; byteBuffer->position++) {
140
- byteBuffer->buffer[byteBuffer->position] = temp[i++];
141
- }
142
- }
110
+ buffer->position = 0;
111
+ buffer->limit = buffer->capacity;
112
+ buffer->mark = MARK_UNSET;
143
113
 
144
114
  return self;
145
115
  }
146
116
 
147
- static VALUE NIO_ByteBuffer_get(VALUE self)
117
+ static VALUE NIO_ByteBuffer_get_position(VALUE self)
118
+ {
119
+ struct NIO_ByteBuffer *buffer;
120
+ Data_Get_Struct(self, struct NIO_ByteBuffer, buffer);
121
+
122
+ return INT2NUM(buffer->position);
123
+ }
124
+
125
+ static VALUE NIO_ByteBuffer_set_position(VALUE self, VALUE new_position)
148
126
  {
149
- struct NIO_ByteBuffer *byteBuffer;
150
- Data_Get_Struct(self, struct NIO_ByteBuffer, byteBuffer);
127
+ struct NIO_ByteBuffer *buffer;
128
+ Data_Get_Struct(self, struct NIO_ByteBuffer, buffer);
129
+
130
+ int pos = NUM2INT(new_position);
151
131
 
152
- int remaining = NUM2INT(NIO_ByteBuffer_remaining(self));
132
+ if(pos < 0) {
133
+ rb_raise(rb_eArgError, "negative position given");
134
+ }
153
135
 
154
- if(remaining == 0) {
155
- return rb_str_new2("");
136
+ if(pos > buffer->limit) {
137
+ rb_raise(rb_eArgError, "specified position exceeds limit");
156
138
  }
157
139
 
158
- char tempArray[remaining+1];
159
- int i = 0;
140
+ buffer->position = pos;
160
141
 
161
- for(byteBuffer->position; byteBuffer->position <= byteBuffer->limit; byteBuffer->position++) {
162
- tempArray[i++] = byteBuffer->buffer[byteBuffer->position];
142
+ if(buffer->mark > buffer->position) {
143
+ buffer->mark = MARK_UNSET;
163
144
  }
164
145
 
165
- tempArray[remaining] = '\0';
166
- return rb_str_new2(tempArray);
146
+ return new_position;
147
+ }
148
+
149
+ static VALUE NIO_ByteBuffer_get_limit(VALUE self)
150
+ {
151
+ struct NIO_ByteBuffer *buffer;
152
+ Data_Get_Struct(self, struct NIO_ByteBuffer, buffer);
153
+
154
+ return INT2NUM(buffer->limit);
167
155
  }
168
156
 
169
- static VALUE NIO_ByteBuffer_readnext(VALUE self, VALUE amount)
157
+ static VALUE NIO_ByteBuffer_set_limit(VALUE self, VALUE new_limit)
170
158
  {
171
- int amnt = NUM2INT(amount);
172
- if(amnt < 1) {
173
- rb_raise(rb_eTypeError, "not a valid input");
159
+ struct NIO_ByteBuffer *buffer;
160
+ Data_Get_Struct(self, struct NIO_ByteBuffer, buffer);
161
+
162
+ int lim = NUM2INT(new_limit);
163
+
164
+ if(lim < 0) {
165
+ rb_raise(rb_eArgError, "negative limit given");
174
166
  }
175
167
 
176
- if(amnt > NUM2INT(NIO_ByteBuffer_remaining(self))) {
177
- rb_raise(rb_eTypeError, "Less number of elements remaining");
168
+ if(lim > buffer->capacity) {
169
+ rb_raise(rb_eArgError, "specified limit exceeds capacity");
178
170
  }
179
171
 
180
- char tempArray[amnt+1];
181
- int c = 0;
182
- struct NIO_ByteBuffer *byteBuffer;
183
- Data_Get_Struct(self, struct NIO_ByteBuffer, byteBuffer);
172
+ buffer->limit = lim;
173
+
174
+ if(buffer->position > lim) {
175
+ buffer->position = lim;
176
+ }
184
177
 
185
- while(c < amnt) {
186
- tempArray[c++] = byteBuffer->buffer[byteBuffer->position];
187
- byteBuffer->position++;
178
+ if(buffer->mark > lim) {
179
+ buffer->mark = MARK_UNSET;
188
180
  }
189
181
 
190
- tempArray[amnt] = '\0';
191
- return rb_str_new2(tempArray);
182
+ return new_limit;
192
183
  }
193
184
 
194
- static VALUE NIO_ByteBuffer_writeTo(VALUE self, VALUE io)
185
+ static VALUE NIO_ByteBuffer_capacity(VALUE self)
195
186
  {
196
- struct NIO_ByteBuffer *byteBuffer;
197
- Data_Get_Struct(self, struct NIO_ByteBuffer, byteBuffer);
198
- int size = byteBuffer->limit + 1 - byteBuffer->position;
187
+ struct NIO_ByteBuffer *buffer;
188
+ Data_Get_Struct(self, struct NIO_ByteBuffer, buffer);
199
189
 
200
- #if HAVE_RB_IO_T
201
- rb_io_t *fptr;
202
- #else
203
- OpenFile *fptr;
204
- #endif
190
+ return INT2NUM(buffer->capacity);
191
+ }
205
192
 
206
- GetOpenFile(rb_convert_type(io, T_FILE, "IO", "to_io"), fptr);
207
- rb_io_set_nonblock(fptr);
193
+ static VALUE NIO_ByteBuffer_remaining(VALUE self)
194
+ {
195
+ struct NIO_ByteBuffer *buffer;
196
+ Data_Get_Struct(self, struct NIO_ByteBuffer, buffer);
208
197
 
209
- VALUE content = NIO_ByteBuffer_get(self);
210
- char* contentAsPointer = StringValuePtr(content);
198
+ return INT2NUM(buffer->limit - buffer->position);
199
+ }
211
200
 
212
- write(FPTR_TO_FD(fptr), contentAsPointer , size);
201
+ static VALUE NIO_ByteBuffer_full(VALUE self)
202
+ {
203
+ struct NIO_ByteBuffer *buffer;
204
+ Data_Get_Struct(self, struct NIO_ByteBuffer, buffer);
213
205
 
214
- return self;
206
+ return buffer->position == buffer->limit ? Qtrue : Qfalse;
215
207
  }
216
208
 
217
- static VALUE NIO_ByteBuffer_readFrom(VALUE self, VALUE io)
209
+ static VALUE NIO_ByteBuffer_get(int argc, VALUE *argv, VALUE self)
218
210
  {
219
- struct NIO_ByteBuffer *byteBuffer;
220
- Data_Get_Struct(self, struct NIO_ByteBuffer, byteBuffer);
221
- int size = byteBuffer->limit + 1 - byteBuffer->position;
211
+ int len;
212
+ VALUE length, result;
213
+ struct NIO_ByteBuffer *buffer;
214
+ Data_Get_Struct(self, struct NIO_ByteBuffer, buffer);
222
215
 
223
- #if HAVE_RB_IO_T
224
- rb_io_t *fptr;
225
- #else
226
- OpenFile *fptr;
227
- #endif
216
+ rb_scan_args(argc, argv, "01", &length);
228
217
 
229
- GetOpenFile(rb_convert_type(io, T_FILE, "IO", "to_io"), fptr);
230
- rb_io_set_nonblock(fptr);
218
+ if(length == Qnil) {
219
+ len = buffer->limit - buffer->position;
220
+ } else {
221
+ len = NUM2INT(length);
222
+ }
231
223
 
232
- while(NIO_ByteBuffer_hasRemaining(self) == Qtrue) {
233
- char* nextByte;
234
- read(FPTR_TO_FD(fptr), &nextByte, 1);
235
- VALUE byte = rb_str_new2(nextByte);
236
- NIO_ByteBuffer_put(self, byte);
224
+ if(len < 0) {
225
+ rb_raise(rb_eArgError, "negative length given");
237
226
  }
238
227
 
239
- return self;
240
- }
228
+ if(len > buffer->limit - buffer->position) {
229
+ rb_raise(cNIO_ByteBuffer_UnderflowError, "not enough data in buffer");
230
+ }
241
231
 
242
- static VALUE NIO_ByteBuffer_remaining(VALUE self)
243
- {
244
- struct NIO_ByteBuffer *byteBuffer;
245
- Data_Get_Struct(self, struct NIO_ByteBuffer, byteBuffer);
232
+ result = rb_str_new(buffer->buffer + buffer->position, len);
233
+ buffer->position += len;
246
234
 
247
- return INT2NUM(byteBuffer->limit + 1 - byteBuffer->position);
235
+ return result;
248
236
  }
249
237
 
250
- static VALUE NIO_ByteBuffer_hasRemaining(VALUE self)
238
+ static VALUE NIO_ByteBuffer_fetch(VALUE self, VALUE index)
251
239
  {
252
- struct NIO_ByteBuffer *byteBuffer;
253
- Data_Get_Struct(self, struct NIO_ByteBuffer, byteBuffer);
240
+ struct NIO_ByteBuffer *buffer;
241
+ Data_Get_Struct(self, struct NIO_ByteBuffer, buffer);
254
242
 
255
- return ((byteBuffer->limit + 1 - byteBuffer->position) > 0) ? Qtrue : Qfalse;
256
- }
243
+ int i = NUM2INT(index);
257
244
 
258
- static VALUE NIO_ByteBuffer_getOffset(VALUE self)
259
- {
260
- struct NIO_ByteBuffer *byteBuffer;
261
- Data_Get_Struct(self, struct NIO_ByteBuffer, byteBuffer);
262
- return INT2NUM(byteBuffer->offset);
263
- }
245
+ if(i < 0) {
246
+ rb_raise(rb_eArgError, "negative index given");
247
+ }
264
248
 
265
- static VALUE NIO_ByteBuffer_equals(VALUE self, VALUE other)
266
- {
267
- return self == other ? Qtrue : Qfalse;
249
+ if(i >= buffer->limit) {
250
+ rb_raise(rb_eArgError, "specified index exceeds limit");
251
+ }
252
+
253
+ return INT2NUM(buffer->buffer[i]);
268
254
  }
269
255
 
270
- static VALUE NIO_ByteBuffer_flip(VALUE self)
256
+ static VALUE NIO_ByteBuffer_put(VALUE self, VALUE string)
271
257
  {
272
- struct NIO_ByteBuffer *byteBuffer;
273
- Data_Get_Struct(self, struct NIO_ByteBuffer, byteBuffer);
258
+ struct NIO_ByteBuffer *buffer;
259
+ Data_Get_Struct(self, struct NIO_ByteBuffer, buffer);
260
+
261
+ long length = RSTRING_LEN(string);
262
+
263
+ if(length > buffer->limit - buffer->position) {
264
+ rb_raise(cNIO_ByteBuffer_OverflowError, "buffer is full");
265
+ }
274
266
 
275
- byteBuffer->limit = (byteBuffer->position > 0) ? byteBuffer->position - 1 : 0;
276
- byteBuffer->position = 0;
277
- byteBuffer->mark = -1;
267
+ memcpy(buffer->buffer + buffer->position, StringValuePtr(string), length);
268
+ buffer->position += length;
278
269
 
279
270
  return self;
280
271
  }
281
272
 
282
- static VALUE NIO_ByteBuffer_rewind(VALUE self)
273
+ static VALUE NIO_ByteBuffer_read_from(VALUE self, VALUE io)
283
274
  {
284
- struct NIO_ByteBuffer *byteBuffer;
285
- Data_Get_Struct(self, struct NIO_ByteBuffer, byteBuffer);
275
+ struct NIO_ByteBuffer *buffer;
276
+ rb_io_t *fptr;
277
+ ssize_t nbytes, bytes_read;
286
278
 
287
- byteBuffer->position = 0;
288
- byteBuffer->mark = -1;
279
+ Data_Get_Struct(self, struct NIO_ByteBuffer, buffer);
280
+ GetOpenFile(rb_convert_type(io, T_FILE, "IO", "to_io"), fptr);
281
+ rb_io_set_nonblock(fptr);
289
282
 
290
- return self;
291
- }
283
+ nbytes = buffer->limit - buffer->position;
284
+ if(nbytes == 0) {
285
+ rb_raise(cNIO_ByteBuffer_OverflowError, "buffer is full");
286
+ }
292
287
 
293
- static VALUE NIO_ByteBuffer_reset(VALUE self)
294
- {
295
- struct NIO_ByteBuffer *byteBuffer;
296
- Data_Get_Struct(self, struct NIO_ByteBuffer, byteBuffer);
288
+ bytes_read = read(FPTR_TO_FD(fptr), buffer->buffer + buffer->position, nbytes);
297
289
 
298
- if(byteBuffer->mark < 0){
299
- rb_raise(rb_eRuntimeError, "Invalid Mark Exception");
300
- } else {
301
- byteBuffer->position = byteBuffer->mark;
290
+ if(bytes_read < 0) {
291
+ if(errno == EAGAIN) {
292
+ return INT2NUM(0);
293
+ } else {
294
+ rb_sys_fail("write");
295
+ }
302
296
  }
303
297
 
304
- return self;
298
+ buffer->position += bytes_read;
299
+
300
+ return INT2NUM(bytes_read);
305
301
  }
306
302
 
307
- static VALUE NIO_ByteBuffer_markBuffer(VALUE self)
303
+ static VALUE NIO_ByteBuffer_write_to(VALUE self, VALUE io)
308
304
  {
309
- struct NIO_ByteBuffer *byteBuffer;
310
- Data_Get_Struct(self, struct NIO_ByteBuffer, byteBuffer);
305
+ struct NIO_ByteBuffer *buffer;
306
+ rb_io_t *fptr;
307
+ ssize_t nbytes, bytes_written;
311
308
 
312
- byteBuffer->mark = byteBuffer->position;
313
- return self;
309
+ Data_Get_Struct(self, struct NIO_ByteBuffer, buffer);
310
+ GetOpenFile(rb_convert_type(io, T_FILE, "IO", "to_io"), fptr);
311
+ rb_io_set_nonblock(fptr);
312
+
313
+ nbytes = buffer->limit - buffer->position;
314
+ if(nbytes == 0) {
315
+ rb_raise(cNIO_ByteBuffer_UnderflowError, "no data remaining in buffer");
316
+ }
317
+
318
+ bytes_written = write(FPTR_TO_FD(fptr), buffer->buffer + buffer->position, nbytes);
319
+
320
+ if(bytes_written < 0) {
321
+ if(errno == EAGAIN) {
322
+ return INT2NUM(0);
323
+ } else {
324
+ rb_sys_fail("write");
325
+ }
326
+ }
327
+
328
+ buffer->position += bytes_written;
329
+
330
+ return INT2NUM(bytes_written);
314
331
  }
315
332
 
316
- static VALUE NIO_ByteBuffer_clear(VALUE self)
333
+ static VALUE NIO_ByteBuffer_flip(VALUE self)
317
334
  {
318
- struct NIO_ByteBuffer *byteBuffer;
319
- Data_Get_Struct(self, struct NIO_ByteBuffer, byteBuffer);
335
+ struct NIO_ByteBuffer *buffer;
336
+ Data_Get_Struct(self, struct NIO_ByteBuffer, buffer);
320
337
 
321
- byteBuffer->position = 0;
322
- byteBuffer->limit = byteBuffer->size - 1;
323
- byteBuffer->mark = -1;
338
+ buffer->limit = buffer->position;
339
+ buffer->position = 0;
340
+ buffer->mark = MARK_UNSET;
324
341
 
325
342
  return self;
326
343
  }
327
344
 
328
- static VALUE NIO_ByteBuffer_compact(VALUE self)
345
+ static VALUE NIO_ByteBuffer_rewind(VALUE self)
329
346
  {
330
- struct NIO_ByteBuffer *byteBuffer;
331
- Data_Get_Struct(self, struct NIO_ByteBuffer, byteBuffer);
332
-
333
- if(NIO_ByteBuffer_hasRemaining(self) == Qtrue) {
334
- //move content
335
- int i = 0, j = byteBuffer->position;
336
- for(j = byteBuffer->position; j <= byteBuffer->limit; j++) {
337
- byteBuffer->buffer[i++] = byteBuffer->buffer[j];
338
- }
347
+ struct NIO_ByteBuffer *buffer;
348
+ Data_Get_Struct(self, struct NIO_ByteBuffer, buffer);
339
349
 
340
- byteBuffer->position = i;
341
- byteBuffer->limit = byteBuffer->size - 1;
342
- }
350
+ buffer->position = 0;
351
+ buffer->mark = MARK_UNSET;
343
352
 
344
353
  return self;
345
354
  }
346
355
 
347
- static VALUE NIO_ByteBuffer_capacity(VALUE self)
356
+ static VALUE NIO_ByteBuffer_mark(VALUE self)
348
357
  {
349
- struct NIO_ByteBuffer *byteBuffer;
350
- Data_Get_Struct(self, struct NIO_ByteBuffer, byteBuffer);
358
+ struct NIO_ByteBuffer *buffer;
359
+ Data_Get_Struct(self, struct NIO_ByteBuffer, buffer);
351
360
 
352
- return INT2NUM(byteBuffer->size);
361
+ buffer->mark = buffer->position;
362
+ return self;
353
363
  }
354
364
 
355
- static VALUE NIO_ByteBuffer_position(VALUE self, VALUE newposition)
365
+ static VALUE NIO_ByteBuffer_reset(VALUE self)
356
366
  {
357
- struct NIO_ByteBuffer *byteBuffer;
358
- Data_Get_Struct(self, struct NIO_ByteBuffer, byteBuffer);
367
+ struct NIO_ByteBuffer *buffer;
368
+ Data_Get_Struct(self, struct NIO_ByteBuffer, buffer);
359
369
 
360
- int newPosition = NUM2INT(newposition);
361
-
362
- if(newPosition < 0 || newPosition > byteBuffer->limit) {
363
- rb_raise(rb_eRuntimeError, "Illegal Argument Exception");
370
+ if(buffer->mark < 0) {
371
+ rb_raise(cNIO_ByteBuffer_MarkUnsetError, "mark has not been set");
364
372
  } else {
365
- byteBuffer->position = newPosition;
366
-
367
- if(byteBuffer->mark > newPosition) {
368
- byteBuffer->mark = -1;
369
- }
373
+ buffer->position = buffer->mark;
370
374
  }
375
+
371
376
  return self;
372
377
  }
373
378
 
374
- static VALUE NIO_ByteBuffer_setLimit(VALUE self, VALUE newlimit)
379
+ static VALUE NIO_ByteBuffer_compact(VALUE self)
375
380
  {
376
- struct NIO_ByteBuffer *byteBuffer;
377
- Data_Get_Struct(self, struct NIO_ByteBuffer, byteBuffer);
381
+ struct NIO_ByteBuffer *buffer;
382
+ Data_Get_Struct(self, struct NIO_ByteBuffer, buffer);
378
383
 
379
- int newLimit = NUM2INT(newlimit);
384
+ memmove(buffer->buffer, buffer->buffer + buffer->position, buffer->limit - buffer->position);
385
+ buffer->position = buffer->limit - buffer->position;
386
+ buffer->limit = buffer->capacity;
380
387
 
381
- if(newLimit < byteBuffer->size && newLimit >= 0)
382
- {
383
- byteBuffer->limit = newLimit;
388
+ return self;
389
+ }
384
390
 
385
- if(byteBuffer->position > byteBuffer->limit) {
386
- byteBuffer->position = newLimit;
387
- }
391
+ static VALUE NIO_ByteBuffer_each(VALUE self)
392
+ {
393
+ int i;
394
+ struct NIO_ByteBuffer *buffer;
395
+ Data_Get_Struct(self, struct NIO_ByteBuffer, buffer);
388
396
 
389
- if(byteBuffer->mark > byteBuffer->limit) {
390
- byteBuffer->mark = -1;
397
+ if(rb_block_given_p()) {
398
+ for(i = 0; i < buffer->limit; i++) {
399
+ rb_yield(INT2NUM(buffer->buffer[i]));
391
400
  }
392
401
  } else {
393
- rb_raise(rb_eRuntimeError, "Illegal Argument Exception");
402
+ rb_raise(rb_eArgError, "no block given");
394
403
  }
395
404
 
396
405
  return self;
397
406
  }
398
407
 
399
- static VALUE NIO_ByteBuffer_getLimit(VALUE self)
408
+ static VALUE NIO_ByteBuffer_inspect(VALUE self)
400
409
  {
401
- struct NIO_ByteBuffer *byteBuffer;
402
- Data_Get_Struct(self, struct NIO_ByteBuffer, byteBuffer);
403
-
404
- return INT2NUM(byteBuffer->limit);
405
- }
406
-
407
- static VALUE NIO_ByteBuffer_toString(VALUE self)
408
- {
409
- struct NIO_ByteBuffer *byteBuffer;
410
- Data_Get_Struct(self, struct NIO_ByteBuffer, byteBuffer);
411
-
412
- return rb_sprintf ("ByteBuffer [pos=%d lim=%d cap=%d]\n", byteBuffer->position, byteBuffer->limit, byteBuffer->size);
410
+ struct NIO_ByteBuffer *buffer;
411
+ Data_Get_Struct(self, struct NIO_ByteBuffer, buffer);
412
+
413
+ return rb_sprintf(
414
+ "#<%s:%p @position=%d @limit=%d @capacity=%d>",
415
+ rb_class2name(CLASS_OF(self)),
416
+ (void*)self,
417
+ buffer->position,
418
+ buffer->limit,
419
+ buffer->capacity
420
+ );
413
421
  }