nio4r 1.2.1 → 2.0.0.pre

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 40a72f524510c03062dc6c3dbf8a6a20236b1f25
4
- data.tar.gz: 0378f2eeeb4ab372da04f9a2f1010d4847c85587
3
+ metadata.gz: f6641deb5a7b32db8287d8856510a07dd33ec737
4
+ data.tar.gz: e414ccbb0aef8b0d8cf9ab63e09154753652766b
5
5
  SHA512:
6
- metadata.gz: 02c255084b29eccedf83860ece30471660af81abcf294cc332cd86816c963ff53e81d1fa4ed7f84108e33762775b08fbf124877452690dfe4755d23cb5788bf4
7
- data.tar.gz: 6b5e34b3863e6cfe1311f4aed6706de099cc09371a2fb8a6439c6a5f164afa2511a18cf0086abded3541770561342c0d6a58ad4e96aaa6b5d7021e66054f1bbe
6
+ metadata.gz: 37539315f05ec820ec9a5644acb178c49098e6384955ce234c7b5d4f137d8122d98a8486e9ebc419250057b4268d55f72f82ca28145c2ebf713af7823bd9a7fb
7
+ data.tar.gz: 1c151cb3ac3d8aef61665ebf4827b59712509d2482c1b26ad1af2853711e6888c8043306a312d4d84b89f511085c346ade0915e768307811bddabc2cc39c41ae
data/.travis.yml CHANGED
@@ -1,26 +1,44 @@
1
1
  language: ruby
2
2
  sudo: false
3
+ cache: bundler
4
+
5
+ bundler_args: --without development
6
+
7
+ branches:
8
+ only:
9
+ - master
10
+
11
+ os:
12
+ - linux
13
+ - osx
3
14
 
4
15
  rvm:
5
- - 2.0.0
6
- - 2.1.1
7
- - 2.2.2
16
+ - 2.0
17
+ - 2.1
18
+ - 2.2
19
+ - 2.3.1
8
20
  - ruby-head
9
- - jruby
21
+ - jruby-9.1.5.0 # latest stable
10
22
  - jruby-head
11
- - rbx-2
23
+ - rbx
12
24
 
13
25
  env:
14
- - NIO4R_PURE=false
15
- - NIO4R_PURE=true
26
+ global:
27
+ - JRUBY_OPTS="--dev -J-Djruby.launch.inproc=true -J-Xmx1024M"
28
+ matrix:
29
+ - NIO4R_PURE=false
30
+ - NIO4R_PURE=true
16
31
 
17
32
  matrix:
18
33
  fast_finish: true
19
34
  allow_failures:
35
+ - os: osx # TODO: make tests pass reliably on OS X
20
36
  - rvm: ruby-head
21
37
  - rvm: jruby-head
22
- - rvm: rbx-2
23
- - rvm: jruby
38
+ - rvm: rbx
39
+ - rvm: jruby-1.7
40
+ env: NIO4R_PURE=true
41
+ - rvm: jruby-9.1
24
42
  env: NIO4R_PURE=true
25
43
 
26
44
  notifications:
data/Gemfile CHANGED
@@ -4,12 +4,9 @@ gemspec
4
4
 
5
5
  gem "jruby-openssl" if defined? JRUBY_VERSION
6
6
 
7
- group :development do
7
+ group :development, :test do
8
8
  gem "rake-compiler"
9
- end
10
-
11
- group :test do
12
- gem "rspec", "~> 3.0"
13
- gem "rubocop", "0.36.0"
14
- gem "coveralls", require: false
9
+ gem "rspec", "~> 3", require: false
10
+ gem "rubocop", "0.36.0", require: false
11
+ gem "coveralls", require: false
15
12
  end
data/README.md CHANGED
@@ -1,47 +1,52 @@
1
- ![nio4r](https://raw.github.com/celluloid/nio4r/master/logo.png)
2
- ===============
1
+ # ![nio4r](https://raw.github.com/celluloid/nio4r/master/logo.png)
2
+
3
3
  [![Gem Version](https://badge.fury.io/rb/nio4r.svg)](http://rubygems.org/gems/nio4r)
4
4
  [![Build Status](https://secure.travis-ci.org/celluloid/nio4r.svg?branch=master)](http://travis-ci.org/celluloid/nio4r)
5
5
  [![Code Climate](https://codeclimate.com/github/celluloid/nio4r.svg)](https://codeclimate.com/github/celluloid/nio4r)
6
6
  [![Coverage Status](https://coveralls.io/repos/celluloid/nio4r/badge.svg?branch=master)](https://coveralls.io/r/celluloid/nio4r)
7
7
  [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/celluloid/nio4r/blob/master/LICENSE.txt)
8
8
 
9
- nio4r: New IO for Ruby.
9
+ _NOTE: This is the 2.x **development** branch of nio4r. For the 1.x **stable**
10
+ branch (used by [Rails 5]), please see:_
11
+
12
+ https://github.com/celluloid/nio4r/tree/1-x-stable
13
+
14
+ **New I/O for Ruby (nio4r)**: cross-platform asynchronous I/O primitives for
15
+ scalable network clients and servers. Modeled after the Java NIO API, but
16
+ simplified for ease-of-use.
10
17
 
11
- nio4r provides an abstract, cross-platform stateful I/O selector API for Ruby.
18
+ **nio4r** provides an abstract, cross-platform stateful I/O selector API for Ruby.
12
19
  I/O selectors are the heart of "reactor"-based event loops, and monitor
13
20
  multiple I/O objects for various types of readiness, e.g. ready for reading or
14
21
  writing.
15
22
 
16
- The most similar API provided by Ruby today is Kernel.select, however the
17
- select API requires you to pass in arrays of all of the I/O objects you're
18
- interested in every time. nio4r provides a more object-oriented API that lets
19
- you register I/O objects with a selector then handle them when they're selected
20
- for various types of events.
23
+ [Rails 5]: https://rubygems.org/gems/actioncable
21
24
 
22
- nio4r is modeled after the Java NIO API, but simplified for ease-of-use.
25
+ ## Projects using nio4r
23
26
 
24
- Its goals are:
27
+ * [ActionCable]: Rails 5 WebSocket protocol, uses nio4r for a WebSocket server
28
+ * [Celluloid::IO]: Actor-based concurrency framework, uses nio4r for async I/O
29
+
30
+ [ActionCable]: https://rubygems.org/gems/actioncable
31
+ [Celluloid::IO]: https://github.com/celluloid/celluloid-io
32
+
33
+ ## Goals
25
34
 
26
35
  * Expose high-level interfaces for stateful IO selectors
27
36
  * Keep the API small to maximize both portability and performance across many
28
37
  different OSes and Ruby VMs
29
38
  * Provide inherently thread-safe facilities for working with IO objects
30
39
 
31
- [Celluloid::IO](https://github.com/celluloid/celluloid-io) uses nio4r to
32
- monitor multiple IO objects from a single Celluloid actor.
33
-
34
- Supported Platforms
35
- -------------------
40
+ ## Supported platforms
36
41
 
37
- nio4r is known to work on the following Ruby implementations:
42
+ * Ruby 2.0
43
+ * Ruby 2.1
44
+ * Ruby 2.2
45
+ * Ruby 2.3
46
+ * JRuby 9000
47
+ * Pure Ruby using Kernel.select
38
48
 
39
- * MRI/YARV 1.9.3, 2.0.0, 2.1.0
40
- * JRuby 1.7.x
41
- * Rubinius 2.x
42
- * A pure Ruby implementation based on Kernel.select is also provided
43
-
44
- Platform notes:
49
+ ## Platform notes
45
50
 
46
51
  * MRI/YARV and Rubinius implement nio4r with a C extension based on libev,
47
52
  which provides a high performance binding to native IO APIs
@@ -49,8 +54,14 @@ Platform notes:
49
54
  * A pure Ruby implementation is also provided for Ruby implementations which
50
55
  don't implement the MRI C extension API
51
56
 
52
- Usage
53
- -----
57
+ ## Usage
58
+
59
+ If you're interested in using nio4r for a project but just getting started,
60
+ check out this blog post which provides some background and examples:
61
+
62
+ [A gentle introduction to nio4r: low-level portable asynchronous I/O for Ruby][blogpost]
63
+
64
+ [blogpost]: https://tonyarcieri.com/a-gentle-introduction-to-nio4r
54
65
 
55
66
  ### Selectors
56
67
 
@@ -152,10 +163,9 @@ For information on how to compose nio4r selectors inside of event loops,
152
163
  please read the [Flow Control Guide on the
153
164
  Wiki](https://github.com/celluloid/nio4r/wiki/Basic-Flow-Control)
154
165
 
155
- Concurrency
156
- -----------
166
+ ## Concurrency
157
167
 
158
- nio4r provides internal locking to ensure that it's safe to use from multiple
168
+ **nio4r** provides internal locking to ensure that it's safe to use from multiple
159
169
  concurrent threads. Only one thread can select on a NIO::Selector at a given
160
170
  time, and while a thread is selecting other threads are blocked from
161
171
  registering or deregistering IO objects. Once a pending select has completed,
@@ -166,28 +176,18 @@ middle of an NIO::Selector#select operation. This lets other threads that need
166
176
  to communicate immediately with the selector unblock it so it can process
167
177
  other events that it's not presently selecting on.
168
178
 
169
- What nio4r is not
170
- -----------------
179
+ ## Non-goals
171
180
 
172
- nio4r is not a full-featured event framework like EventMachine or Cool.io.
181
+ **nio4r** is not a full-featured event framework like [EventMachine] or [Cool.io].
173
182
  Instead, nio4r is the sort of thing you might write a library like that on
174
183
  top of. nio4r provides a minimal API such that individual Ruby implementers
175
184
  may choose to produce optimized versions for their platform, without having
176
185
  to maintain a large codebase.
177
186
 
178
- As of the time of writing, the current implementation is (approximately):
179
-
180
- * 200 lines of Ruby code
181
- * 700 lines of "custom" C code (not counting libev)
182
- * 400 lines of Java code
183
-
184
- nio4r is also not a replacement for Kinder Gentler IO (KGIO), a set of
185
- advanced Ruby IO APIs. At some point in the future nio4r might provide a
186
- cross-platform implementation that uses KGIO on CRubies, and Java NIO on JRuby,
187
- however this is not the case today.
187
+ [EventMachine]: https://github.com/eventmachine/eventmachine
188
+ [Cool.io]: https://coolio.github.io/
188
189
 
189
- License
190
- -------
190
+ ## License
191
191
 
192
192
  Copyright (c) 2011-2016 Tony Arcieri. Distributed under the MIT License.
193
193
  See LICENSE.txt for further details.
data/Rakefile CHANGED
@@ -1,4 +1,3 @@
1
- #!/usr/bin/env rake
2
1
  require "bundler/gem_tasks"
3
2
  require "rake/clean"
4
3
 
File without changes
data/ext/libev/ev.c CHANGED
@@ -39,6 +39,7 @@
39
39
 
40
40
  /* ########## NIO4R PATCHERY HO! ########## */
41
41
  #include "ruby.h"
42
+ #include "ruby/thread.h"
42
43
  /* ######################################## */
43
44
 
44
45
  /* this big block deduces configuration from config.h */
@@ -0,0 +1,413 @@
1
+ #include "nio4r.h"
2
+
3
+ static VALUE mNIO = Qnil;
4
+ static VALUE cNIO_ByteBuffer = Qnil;
5
+
6
+ /* Allocator/deallocator */
7
+ static VALUE NIO_ByteBuffer_allocate(VALUE klass);
8
+ static void NIO_ByteBuffer_mark(struct NIO_ByteBuffer *byteBuffer);
9
+ static void NIO_ByteBuffer_free(struct NIO_ByteBuffer *byteBuffer);
10
+
11
+ /* 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);
18
+ 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);
22
+ static VALUE NIO_ByteBuffer_flip(VALUE self);
23
+ static VALUE NIO_ByteBuffer_rewind(VALUE self);
24
+ static VALUE NIO_ByteBuffer_reset(VALUE self);
25
+ static VALUE NIO_ByteBuffer_markBuffer(VALUE self);
26
+ static VALUE NIO_ByteBuffer_clear(VALUE self);
27
+ 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);
33
+
34
+ void Init_NIO_ByteBuffer()
35
+ {
36
+ mNIO = rb_define_module("NIO");
37
+ cNIO_ByteBuffer = rb_define_class_under(mNIO, "ByteBuffer", rb_cObject);
38
+ rb_define_alloc_func(cNIO_ByteBuffer, NIO_ByteBuffer_allocate);
39
+
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);
46
+ 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);
50
+ rb_define_method(cNIO_ByteBuffer, "flip", NIO_ByteBuffer_flip, 0);
51
+ rb_define_method(cNIO_ByteBuffer, "rewind", NIO_ByteBuffer_rewind, 0);
52
+ 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
+ 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);
61
+ }
62
+
63
+ static VALUE NIO_ByteBuffer_allocate(VALUE klass)
64
+ {
65
+ 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);
67
+ }
68
+
69
+ static void NIO_ByteBuffer_mark(struct NIO_ByteBuffer *buffer)
70
+ {
71
+ }
72
+
73
+ static void NIO_ByteBuffer_free(struct NIO_ByteBuffer *buffer)
74
+ {
75
+ xfree(buffer);
76
+ }
77
+
78
+ static VALUE NIO_ByteBuffer_initialize(VALUE self, VALUE value, VALUE i_offset, VALUE i_length)
79
+ {
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;
106
+
107
+ if(i_offset != Qnil && TYPE(i_offset) == T_FIXNUM) {
108
+ byteBuffer->offset = NUM2INT(i_offset);
109
+ byteBuffer->position = byteBuffer->offset;
110
+
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
+ }
125
+
126
+ return self;
127
+ }
128
+
129
+ static VALUE NIO_ByteBuffer_put(VALUE self, VALUE string)
130
+ {
131
+ struct NIO_ByteBuffer *byteBuffer;
132
+ Data_Get_Struct(self, struct NIO_ByteBuffer, byteBuffer);
133
+
134
+ if(TYPE(string) == T_STRING) {
135
+ char *temp = StringValuePtr(string);
136
+ int i = 0;
137
+ int limit = RSTRING_LEN(string);
138
+
139
+ for(byteBuffer->position; i < limit; byteBuffer->position++) {
140
+ byteBuffer->buffer[byteBuffer->position] = temp[i++];
141
+ }
142
+ }
143
+
144
+ return self;
145
+ }
146
+
147
+ static VALUE NIO_ByteBuffer_get(VALUE self)
148
+ {
149
+ struct NIO_ByteBuffer *byteBuffer;
150
+ Data_Get_Struct(self, struct NIO_ByteBuffer, byteBuffer);
151
+
152
+ int remaining = NUM2INT(NIO_ByteBuffer_remaining(self));
153
+
154
+ if(remaining == 0) {
155
+ return rb_str_new2("");
156
+ }
157
+
158
+ char tempArray[remaining+1];
159
+ int i = 0;
160
+
161
+ for(byteBuffer->position; byteBuffer->position <= byteBuffer->limit; byteBuffer->position++) {
162
+ tempArray[i++] = byteBuffer->buffer[byteBuffer->position];
163
+ }
164
+
165
+ tempArray[remaining] = '\0';
166
+ return rb_str_new2(tempArray);
167
+ }
168
+
169
+ static VALUE NIO_ByteBuffer_readnext(VALUE self, VALUE amount)
170
+ {
171
+ int amnt = NUM2INT(amount);
172
+ if(amnt < 1) {
173
+ rb_raise(rb_eTypeError, "not a valid input");
174
+ }
175
+
176
+ if(amnt > NUM2INT(NIO_ByteBuffer_remaining(self))) {
177
+ rb_raise(rb_eTypeError, "Less number of elements remaining");
178
+ }
179
+
180
+ char tempArray[amnt+1];
181
+ int c = 0;
182
+ struct NIO_ByteBuffer *byteBuffer;
183
+ Data_Get_Struct(self, struct NIO_ByteBuffer, byteBuffer);
184
+
185
+ while(c < amnt) {
186
+ tempArray[c++] = byteBuffer->buffer[byteBuffer->position];
187
+ byteBuffer->position++;
188
+ }
189
+
190
+ tempArray[amnt] = '\0';
191
+ return rb_str_new2(tempArray);
192
+ }
193
+
194
+ static VALUE NIO_ByteBuffer_writeTo(VALUE self, VALUE io)
195
+ {
196
+ struct NIO_ByteBuffer *byteBuffer;
197
+ Data_Get_Struct(self, struct NIO_ByteBuffer, byteBuffer);
198
+ int size = byteBuffer->limit + 1 - byteBuffer->position;
199
+
200
+ #if HAVE_RB_IO_T
201
+ rb_io_t *fptr;
202
+ #else
203
+ OpenFile *fptr;
204
+ #endif
205
+
206
+ GetOpenFile(rb_convert_type(io, T_FILE, "IO", "to_io"), fptr);
207
+ rb_io_set_nonblock(fptr);
208
+
209
+ VALUE content = NIO_ByteBuffer_get(self);
210
+ char* contentAsPointer = StringValuePtr(content);
211
+
212
+ write(FPTR_TO_FD(fptr), contentAsPointer , size);
213
+
214
+ return self;
215
+ }
216
+
217
+ static VALUE NIO_ByteBuffer_readFrom(VALUE self, VALUE io)
218
+ {
219
+ struct NIO_ByteBuffer *byteBuffer;
220
+ Data_Get_Struct(self, struct NIO_ByteBuffer, byteBuffer);
221
+ int size = byteBuffer->limit + 1 - byteBuffer->position;
222
+
223
+ #if HAVE_RB_IO_T
224
+ rb_io_t *fptr;
225
+ #else
226
+ OpenFile *fptr;
227
+ #endif
228
+
229
+ GetOpenFile(rb_convert_type(io, T_FILE, "IO", "to_io"), fptr);
230
+ rb_io_set_nonblock(fptr);
231
+
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);
237
+ }
238
+
239
+ return self;
240
+ }
241
+
242
+ static VALUE NIO_ByteBuffer_remaining(VALUE self)
243
+ {
244
+ struct NIO_ByteBuffer *byteBuffer;
245
+ Data_Get_Struct(self, struct NIO_ByteBuffer, byteBuffer);
246
+
247
+ return INT2NUM(byteBuffer->limit + 1 - byteBuffer->position);
248
+ }
249
+
250
+ static VALUE NIO_ByteBuffer_hasRemaining(VALUE self)
251
+ {
252
+ struct NIO_ByteBuffer *byteBuffer;
253
+ Data_Get_Struct(self, struct NIO_ByteBuffer, byteBuffer);
254
+
255
+ return ((byteBuffer->limit + 1 - byteBuffer->position) > 0) ? Qtrue : Qfalse;
256
+ }
257
+
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
+ }
264
+
265
+ static VALUE NIO_ByteBuffer_equals(VALUE self, VALUE other)
266
+ {
267
+ return self == other ? Qtrue : Qfalse;
268
+ }
269
+
270
+ static VALUE NIO_ByteBuffer_flip(VALUE self)
271
+ {
272
+ struct NIO_ByteBuffer *byteBuffer;
273
+ Data_Get_Struct(self, struct NIO_ByteBuffer, byteBuffer);
274
+
275
+ byteBuffer->limit = (byteBuffer->position > 0) ? byteBuffer->position - 1 : 0;
276
+ byteBuffer->position = 0;
277
+ byteBuffer->mark = -1;
278
+
279
+ return self;
280
+ }
281
+
282
+ static VALUE NIO_ByteBuffer_rewind(VALUE self)
283
+ {
284
+ struct NIO_ByteBuffer *byteBuffer;
285
+ Data_Get_Struct(self, struct NIO_ByteBuffer, byteBuffer);
286
+
287
+ byteBuffer->position = 0;
288
+ byteBuffer->mark = -1;
289
+
290
+ return self;
291
+ }
292
+
293
+ static VALUE NIO_ByteBuffer_reset(VALUE self)
294
+ {
295
+ struct NIO_ByteBuffer *byteBuffer;
296
+ Data_Get_Struct(self, struct NIO_ByteBuffer, byteBuffer);
297
+
298
+ if(byteBuffer->mark < 0){
299
+ rb_raise(rb_eRuntimeError, "Invalid Mark Exception");
300
+ } else {
301
+ byteBuffer->position = byteBuffer->mark;
302
+ }
303
+
304
+ return self;
305
+ }
306
+
307
+ static VALUE NIO_ByteBuffer_markBuffer(VALUE self)
308
+ {
309
+ struct NIO_ByteBuffer *byteBuffer;
310
+ Data_Get_Struct(self, struct NIO_ByteBuffer, byteBuffer);
311
+
312
+ byteBuffer->mark = byteBuffer->position;
313
+ return self;
314
+ }
315
+
316
+ static VALUE NIO_ByteBuffer_clear(VALUE self)
317
+ {
318
+ struct NIO_ByteBuffer *byteBuffer;
319
+ Data_Get_Struct(self, struct NIO_ByteBuffer, byteBuffer);
320
+
321
+ byteBuffer->position = 0;
322
+ byteBuffer->limit = byteBuffer->size - 1;
323
+ byteBuffer->mark = -1;
324
+
325
+ return self;
326
+ }
327
+
328
+ static VALUE NIO_ByteBuffer_compact(VALUE self)
329
+ {
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
+ }
339
+
340
+ byteBuffer->position = i;
341
+ byteBuffer->limit = byteBuffer->size - 1;
342
+ }
343
+
344
+ return self;
345
+ }
346
+
347
+ static VALUE NIO_ByteBuffer_capacity(VALUE self)
348
+ {
349
+ struct NIO_ByteBuffer *byteBuffer;
350
+ Data_Get_Struct(self, struct NIO_ByteBuffer, byteBuffer);
351
+
352
+ return INT2NUM(byteBuffer->size);
353
+ }
354
+
355
+ static VALUE NIO_ByteBuffer_position(VALUE self, VALUE newposition)
356
+ {
357
+ struct NIO_ByteBuffer *byteBuffer;
358
+ Data_Get_Struct(self, struct NIO_ByteBuffer, byteBuffer);
359
+
360
+ int newPosition = NUM2INT(newposition);
361
+
362
+ if(newPosition < 0 || newPosition > byteBuffer->limit) {
363
+ rb_raise(rb_eRuntimeError, "Illegal Argument Exception");
364
+ } else {
365
+ byteBuffer->position = newPosition;
366
+
367
+ if(byteBuffer->mark > newPosition) {
368
+ byteBuffer->mark = -1;
369
+ }
370
+ }
371
+ return self;
372
+ }
373
+
374
+ static VALUE NIO_ByteBuffer_setLimit(VALUE self, VALUE newlimit)
375
+ {
376
+ struct NIO_ByteBuffer *byteBuffer;
377
+ Data_Get_Struct(self, struct NIO_ByteBuffer, byteBuffer);
378
+
379
+ int newLimit = NUM2INT(newlimit);
380
+
381
+ if(newLimit < byteBuffer->size && newLimit >= 0)
382
+ {
383
+ byteBuffer->limit = newLimit;
384
+
385
+ if(byteBuffer->position > byteBuffer->limit) {
386
+ byteBuffer->position = newLimit;
387
+ }
388
+
389
+ if(byteBuffer->mark > byteBuffer->limit) {
390
+ byteBuffer->mark = -1;
391
+ }
392
+ } else {
393
+ rb_raise(rb_eRuntimeError, "Illegal Argument Exception");
394
+ }
395
+
396
+ return self;
397
+ }
398
+
399
+ static VALUE NIO_ByteBuffer_getLimit(VALUE self)
400
+ {
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);
413
+ }
data/ext/nio4r/nio4r.h CHANGED
@@ -41,6 +41,14 @@ struct NIO_Monitor
41
41
  struct NIO_Selector *selector;
42
42
  };
43
43
 
44
+ struct NIO_ByteBuffer
45
+ {
46
+ int size, offset, limit, position, mark;
47
+ char *buffer;
48
+ VALUE self;
49
+ };
50
+
51
+
44
52
  #ifdef GetReadFile
45
53
  # define FPTR_TO_FD(fptr) (fileno(GetReadFile(fptr)))
46
54
  #else
@@ -8,9 +8,11 @@
8
8
 
9
9
  void Init_NIO_Selector();
10
10
  void Init_NIO_Monitor();
11
+ void Init_NIO_ByteBuffer();
11
12
 
12
13
  void Init_nio4r_ext()
13
14
  {
14
15
  Init_NIO_Selector();
15
16
  Init_NIO_Monitor();
17
+ Init_NIO_ByteBuffer();
16
18
  }