io-extra 1.2.1 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGES +6 -0
- data/README +6 -3
- data/Rakefile +4 -3
- data/ext/extconf.rb +3 -0
- data/ext/io/extra.c +167 -3
- data/io-extra.gemspec +1 -1
- data/test/test_io_extra.rb +139 -95
- metadata +28 -15
data/CHANGES
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
== 1.2.2 - 1-May-2010
|
2
|
+
* Added the IO.writev method which allows you to write arrays without
|
3
|
+
requiring an Array#join call, i.e. "gather write". Thanks go to Eric
|
4
|
+
Wong for supplying the code to support this.
|
5
|
+
* Some Rakefile updates.
|
6
|
+
|
1
7
|
== 1.2.1 - 16-Jan-2010
|
2
8
|
* Some README updates
|
3
9
|
* Updates to the gemspec.
|
data/README
CHANGED
@@ -60,15 +60,18 @@
|
|
60
60
|
documentation that was generated by RDoc (if you did a gem install).
|
61
61
|
|
62
62
|
= Known Issues
|
63
|
-
|
64
|
-
|
63
|
+
The IO.writev tests fail on Solaris. We are not sure why yet.
|
64
|
+
|
65
|
+
Please file any bug reports on the project page at
|
66
|
+
http://www.rubyforge.org/projects/shards.
|
65
67
|
|
66
68
|
= Future Plans
|
67
69
|
* I may add the File::O_DIRECT open constant on platforms that support it.
|
68
70
|
* Switch from C extension to FFI.
|
69
71
|
|
70
72
|
= Acknowledgements
|
71
|
-
Eric Wong for some great work on Linux compatibility and other fixes
|
73
|
+
Eric Wong for some great work on Linux compatibility and other fixes, as
|
74
|
+
well as the code for the IO.writev method.
|
72
75
|
|
73
76
|
= License
|
74
77
|
Artistic 2.0
|
data/Rakefile
CHANGED
@@ -19,6 +19,7 @@ task :clean do
|
|
19
19
|
build_file = File.join(Dir.pwd, 'io', 'extra.' + Config::CONFIG['DLEXT'])
|
20
20
|
File.delete(build_file) if File.exists?(build_file)
|
21
21
|
end
|
22
|
+
Dir['*.gem'].each{ |f| File.delete(f) }
|
22
23
|
end
|
23
24
|
|
24
25
|
desc "Build the io-extra library (but don't install it)"
|
@@ -40,14 +41,14 @@ task :install => [:build] do
|
|
40
41
|
end
|
41
42
|
|
42
43
|
namespace :gem do
|
43
|
-
desc '
|
44
|
-
task :
|
44
|
+
desc 'Create the io-extra gem'
|
45
|
+
task :create do
|
45
46
|
spec = eval(IO.read('io-extra.gemspec'))
|
46
47
|
Gem::Builder.new(spec).build
|
47
48
|
end
|
48
49
|
|
49
50
|
desc "Install the io-extra library as a gem"
|
50
|
-
task :install => [:
|
51
|
+
task :install => [:create] do
|
51
52
|
file = Dir["io-extra*.gem"].last
|
52
53
|
sh "gem install #{file}"
|
53
54
|
end
|
data/ext/extconf.rb
CHANGED
@@ -6,12 +6,15 @@ dir_config('io')
|
|
6
6
|
|
7
7
|
have_header('stdint.h')
|
8
8
|
have_header('sys/resource.h')
|
9
|
+
have_header('sys/uio.h')
|
9
10
|
have_func('closefrom')
|
10
11
|
have_func('fdwalk')
|
11
12
|
have_func('directio')
|
12
13
|
have_func('pread')
|
13
14
|
have_func('pwrite')
|
15
|
+
have_func('writev')
|
14
16
|
have_func('rb_str_set_len', 'ruby.h')
|
17
|
+
have_func('rb_thread_blocking_region')
|
15
18
|
|
16
19
|
case Config::CONFIG['host_os']
|
17
20
|
when /darwin/i
|
data/ext/io/extra.c
CHANGED
@@ -14,6 +14,49 @@
|
|
14
14
|
#include <stdint.h>
|
15
15
|
#endif
|
16
16
|
|
17
|
+
#ifdef HAVE_SYS_UIO_H
|
18
|
+
#include <sys/uio.h>
|
19
|
+
#endif
|
20
|
+
|
21
|
+
#ifdef HAVE_LIMITS_H
|
22
|
+
#include <limits.h>
|
23
|
+
#endif
|
24
|
+
|
25
|
+
#if !defined(IOV_MAX)
|
26
|
+
#if defined(_SC_IOV_MAX)
|
27
|
+
#define IOV_MAX (sysconf(_SC_IOV_MAX))
|
28
|
+
#else
|
29
|
+
/* assume infinity, or let the syscall return with error ... */
|
30
|
+
#define IOV_MAX INT_MAX
|
31
|
+
#endif
|
32
|
+
#endif
|
33
|
+
|
34
|
+
#ifndef HAVE_RB_THREAD_BLOCKING_REGION
|
35
|
+
/*
|
36
|
+
* partial emulation of the 1.9 rb_thread_blocking_region under 1.8,
|
37
|
+
* this is enough to ensure signals are processed safely when doing I/O
|
38
|
+
* to a slow device, but doesn't actually ensure threads can be
|
39
|
+
* scheduled fairly in 1.8
|
40
|
+
*/
|
41
|
+
#include <rubysig.h>
|
42
|
+
#define RUBY_UBF_IO ((rb_unblock_function_t *)-1)
|
43
|
+
typedef void rb_unblock_function_t(void *);
|
44
|
+
typedef VALUE rb_blocking_function_t(void *);
|
45
|
+
static VALUE
|
46
|
+
rb_thread_blocking_region(
|
47
|
+
rb_blocking_function_t *fn, void *data1,
|
48
|
+
rb_unblock_function_t *ubf, void *data2)
|
49
|
+
{
|
50
|
+
VALUE rv;
|
51
|
+
|
52
|
+
TRAP_BEG;
|
53
|
+
rv = fn(data1);
|
54
|
+
TRAP_END;
|
55
|
+
|
56
|
+
return rv;
|
57
|
+
}
|
58
|
+
#endif
|
59
|
+
|
17
60
|
#ifndef RSTRING_PTR
|
18
61
|
#define RSTRING_PTR(v) (RSTRING(v)->ptr)
|
19
62
|
#define RSTRING_LEN(v) (RSTRING(v)->len)
|
@@ -287,7 +330,7 @@ static VALUE s_io_pread(VALUE klass, VALUE v_fd, VALUE v_nbyte, VALUE v_offset){
|
|
287
330
|
|
288
331
|
if (nread < 0)
|
289
332
|
rb_sys_fail("pread");
|
290
|
-
if (nread != nbyte)
|
333
|
+
if ((size_t)nread != nbyte)
|
291
334
|
rb_str_set_len(str, nread);
|
292
335
|
|
293
336
|
return str;
|
@@ -345,6 +388,121 @@ static VALUE s_io_pwrite(VALUE klass, VALUE v_fd, VALUE v_buf, VALUE v_offset){
|
|
345
388
|
}
|
346
389
|
#endif
|
347
390
|
|
391
|
+
/* this can't be a function since we use alloca() */
|
392
|
+
#define ARY2IOVEC(iov,iovcnt,expect,ary) \
|
393
|
+
do { \
|
394
|
+
VALUE *cur; \
|
395
|
+
struct iovec *tmp; \
|
396
|
+
long n; \
|
397
|
+
if (TYPE(ary) != T_ARRAY) \
|
398
|
+
rb_raise(rb_eArgError, "must be an array of strings"); \
|
399
|
+
cur = RARRAY_PTR(ary); \
|
400
|
+
n = RARRAY_LEN(ary); \
|
401
|
+
if (n > IOV_MAX) \
|
402
|
+
rb_raise(rb_eArgError, "array is larger than IOV_MAX"); \
|
403
|
+
iov = tmp = alloca(sizeof(struct iovec) * n); \
|
404
|
+
expect = 0; \
|
405
|
+
iovcnt = (int)n; \
|
406
|
+
for (; --n >= 0; tmp++, cur++) { \
|
407
|
+
if (TYPE(*cur) != T_STRING) \
|
408
|
+
rb_raise(rb_eArgError, "must be an array of strings"); \
|
409
|
+
tmp->iov_base = RSTRING_PTR(*cur); \
|
410
|
+
tmp->iov_len = RSTRING_LEN(*cur); \
|
411
|
+
expect += tmp->iov_len; \
|
412
|
+
} \
|
413
|
+
} while (0)
|
414
|
+
|
415
|
+
#if defined(HAVE_WRITEV)
|
416
|
+
struct writev_args {
|
417
|
+
int fd;
|
418
|
+
struct iovec *iov;
|
419
|
+
int iovcnt;
|
420
|
+
};
|
421
|
+
|
422
|
+
static VALUE nogvl_writev(void *ptr)
|
423
|
+
{
|
424
|
+
struct writev_args *args = ptr;
|
425
|
+
|
426
|
+
return (VALUE)writev(args->fd, args->iov, args->iovcnt);
|
427
|
+
}
|
428
|
+
|
429
|
+
/*
|
430
|
+
* IO.writev(fd, %w(hello world))
|
431
|
+
*
|
432
|
+
* This method writes the contents of an array of strings to the given +fd+.
|
433
|
+
* It can be useful to avoid generating a temporary string via Array#join
|
434
|
+
* when writing out large arrays of strings.
|
435
|
+
*
|
436
|
+
* The given array should have fewer elements than the IO::IOV_MAX constant.
|
437
|
+
*
|
438
|
+
* Returns the number of bytes written.
|
439
|
+
*/
|
440
|
+
static VALUE s_io_writev(VALUE klass, VALUE fd, VALUE ary) {
|
441
|
+
ssize_t result = 0;
|
442
|
+
ssize_t left;
|
443
|
+
struct writev_args args;
|
444
|
+
|
445
|
+
args.fd = NUM2INT(fd);
|
446
|
+
ARY2IOVEC(args.iov, args.iovcnt, left, ary);
|
447
|
+
|
448
|
+
for(;;) {
|
449
|
+
ssize_t w = (ssize_t)rb_thread_blocking_region(nogvl_writev, &args,
|
450
|
+
RUBY_UBF_IO, 0);
|
451
|
+
|
452
|
+
if(w == -1) {
|
453
|
+
if (rb_io_wait_writable(args.fd)) {
|
454
|
+
continue;
|
455
|
+
} else {
|
456
|
+
if (result > 0) {
|
457
|
+
/*
|
458
|
+
* unlikely to hit this case, return the already written bytes,
|
459
|
+
* we'll let the next write (or close) fail instead
|
460
|
+
*/
|
461
|
+
break;
|
462
|
+
}
|
463
|
+
rb_sys_fail("writev");
|
464
|
+
}
|
465
|
+
}
|
466
|
+
|
467
|
+
result += w;
|
468
|
+
if(w == left) {
|
469
|
+
break;
|
470
|
+
} else { /* partial write, this can get tricky */
|
471
|
+
int i;
|
472
|
+
struct iovec *new_iov = args.iov;
|
473
|
+
|
474
|
+
left -= w;
|
475
|
+
|
476
|
+
/* skip over iovecs we've already written completely */
|
477
|
+
for (i = 0; i < args.iovcnt; i++, new_iov++) {
|
478
|
+
if (w == 0)
|
479
|
+
break;
|
480
|
+
|
481
|
+
/*
|
482
|
+
* partially written iov,
|
483
|
+
* modify and retry with current iovec in front
|
484
|
+
*/
|
485
|
+
if (new_iov->iov_len > (size_t)w) {
|
486
|
+
VALUE base = (VALUE)new_iov->iov_base;
|
487
|
+
|
488
|
+
new_iov->iov_len -= w;
|
489
|
+
new_iov->iov_base = (void *)(base + w);
|
490
|
+
break;
|
491
|
+
}
|
492
|
+
|
493
|
+
w -= new_iov->iov_len;
|
494
|
+
}
|
495
|
+
|
496
|
+
/* retry without the already-written iovecs */
|
497
|
+
args.iovcnt -= i;
|
498
|
+
args.iov = new_iov;
|
499
|
+
}
|
500
|
+
}
|
501
|
+
|
502
|
+
return LONG2NUM(result);
|
503
|
+
}
|
504
|
+
#endif
|
505
|
+
|
348
506
|
/* Adds the IO.closefrom, IO.fdwalk class methods, as well as the IO#directio
|
349
507
|
* and IO#directio? instance methods (if supported on your platform).
|
350
508
|
*/
|
@@ -371,6 +529,8 @@ void Init_extra(){
|
|
371
529
|
rb_define_const(rb_cIO, "DIRECT", UINT2NUM(O_DIRECT));
|
372
530
|
#endif
|
373
531
|
|
532
|
+
rb_define_const(rb_cIO, "IOV_MAX", LONG2NUM(IOV_MAX));
|
533
|
+
|
374
534
|
#ifdef HAVE_PREAD
|
375
535
|
rb_define_singleton_method(rb_cIO, "pread", s_io_pread, 3);
|
376
536
|
rb_define_singleton_method(rb_cIO, "pread_ptr", s_io_pread_ptr, 3);
|
@@ -380,6 +540,10 @@ void Init_extra(){
|
|
380
540
|
rb_define_singleton_method(rb_cIO, "pwrite", s_io_pwrite, 3);
|
381
541
|
#endif
|
382
542
|
|
383
|
-
|
384
|
-
|
543
|
+
#ifdef HAVE_WRITEV
|
544
|
+
rb_define_singleton_method(rb_cIO, "writev", s_io_writev, 2);
|
545
|
+
#endif
|
546
|
+
|
547
|
+
/* 1.2.2: The version of this library. This a string. */
|
548
|
+
rb_define_const(rb_cIO, "EXTRA_VERSION", rb_str_new2("1.2.2"));
|
385
549
|
}
|
data/io-extra.gemspec
CHANGED
data/test/test_io_extra.rb
CHANGED
@@ -9,103 +9,147 @@ gem 'test-unit'
|
|
9
9
|
|
10
10
|
require 'test/unit'
|
11
11
|
require 'rbconfig'
|
12
|
+
require 'io/nonblock'
|
12
13
|
require 'io/extra'
|
13
14
|
|
14
15
|
class TC_IO_Extra < Test::Unit::TestCase
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
16
|
+
def setup
|
17
|
+
@file = 'delete_this.txt'
|
18
|
+
@fh = File.open(@file, 'w+')
|
19
|
+
@fh.puts "The quick brown fox jumped over the lazy dog's back"
|
20
|
+
end
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
22
|
+
def test_version
|
23
|
+
assert_equal('1.2.2', IO::EXTRA_VERSION)
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_direct_constant
|
27
|
+
omit_unless(Config::CONFIG['host_os'] =~ /linux/i, 'Linux-only')
|
28
|
+
assert_equal(040000, IO::DIRECT)
|
29
|
+
assert_equal(040000, File::DIRECT)
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_open_direct
|
33
|
+
omit_unless(Config::CONFIG['host_os'] =~ /linux/i, 'Linux-only')
|
34
|
+
assert_nothing_raised do
|
35
|
+
fh = File.open(@fh.path, IO::RDWR|IO::DIRECT)
|
36
|
+
fh.close
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_directio
|
41
|
+
omit_if(Config::CONFIG['host_os'] =~ /darwin/i, 'unsupported')
|
42
|
+
assert_respond_to(@fh, :directio?)
|
43
|
+
assert_nothing_raised{ @fh.directio? }
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_directio_set
|
47
|
+
omit_if(Config::CONFIG['host_os'] =~ /darwin/i, 'unsupported')
|
48
|
+
assert_respond_to(@fh, :directio=)
|
49
|
+
assert_raises(StandardError){ @fh.directio = 99 }
|
50
|
+
assert_nothing_raised{ @fh.directio = IO::DIRECTIO_ON }
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_constants
|
54
|
+
omit_if(Config::CONFIG['host_os'] =~ /darwin/i, 'unsupported')
|
55
|
+
assert_not_nil(IO::DIRECTIO_ON)
|
56
|
+
assert_not_nil(IO::DIRECTIO_OFF)
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_IOV_MAX_constant
|
60
|
+
assert_kind_of(Integer, IO::IOV_MAX)
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_fdwalk
|
64
|
+
omit_if(Config::CONFIG['host_os'] =~ /darwin/i, 'unsupported')
|
65
|
+
assert_respond_to(IO, :fdwalk)
|
66
|
+
assert_nothing_raised{ IO.fdwalk(0){ } }
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_closefrom
|
70
|
+
assert_respond_to(IO, :closefrom)
|
71
|
+
assert_nothing_raised{ IO.closefrom(3) }
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_pread
|
75
|
+
@fh.close rescue nil
|
76
|
+
@fh = File.open(@file)
|
77
|
+
assert_respond_to(IO, :pread)
|
78
|
+
assert_equal("quick", IO.pread(@fh.fileno, 5, 4))
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_pread_binary
|
82
|
+
@fh.close rescue nil
|
83
|
+
@fh = File.open(@file, "ab")
|
84
|
+
@fh.binmode
|
85
|
+
size = @fh.stat.size
|
86
|
+
assert_nothing_raised { @fh.syswrite("FOO\0HELLO") }
|
87
|
+
@fh.close rescue nil
|
88
|
+
@fh = File.open(@file)
|
89
|
+
assert_equal("O\0H", IO.pread(@fh.fileno, 3, size + 2))
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_pread_ptr
|
93
|
+
@fh.close rescue nil
|
94
|
+
@fh = File.open(@file)
|
95
|
+
assert_respond_to(IO, :pread_ptr)
|
96
|
+
assert_kind_of(Integer, IO.pread_ptr(@fh.fileno, 5, 4))
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_pread_last
|
100
|
+
@fh.close rescue nil
|
101
|
+
@fh = File.open(@file)
|
102
|
+
size = @fh.stat.size
|
103
|
+
assert_equal("ck\n", IO.pread(@fh.fileno, 5, size - 3))
|
104
|
+
end
|
105
|
+
|
106
|
+
def test_pwrite
|
107
|
+
assert_respond_to(IO, :pwrite)
|
108
|
+
assert_nothing_raised{ IO.pwrite(@fh.fileno, "HAL", 0) }
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_writev
|
112
|
+
assert_respond_to(IO, :writev)
|
113
|
+
assert_equal(10, IO.writev(@fh.fileno, %w(hello world)))
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_writev_retry
|
117
|
+
empty = ""
|
118
|
+
if empty.respond_to?(:force_encoding)
|
119
|
+
empty.force_encoding(Encoding::BINARY)
|
120
|
+
end
|
121
|
+
|
122
|
+
# bs * count should be > PIPE_BUF
|
123
|
+
[ true, false ].each do |nonblock|
|
124
|
+
[ [ 512, 512 ], [ 131073, 3 ], [ 4098, 64 ] ].each do |(bs,count)|
|
125
|
+
rd, wr = IO.pipe
|
126
|
+
wr.nonblock = nonblock
|
127
|
+
buf = File.open("/dev/urandom", "rb") { |fp| fp.sysread(bs) }
|
128
|
+
vec = (1..count).map { buf }
|
129
|
+
pid = fork do
|
130
|
+
wr.close
|
131
|
+
tmp = []
|
132
|
+
sleep 0.1
|
133
|
+
begin
|
134
|
+
tmp << rd.readpartial(8192, buf)
|
135
|
+
rescue EOFError
|
136
|
+
break
|
137
|
+
end while true
|
138
|
+
ok = (vec.join(empty) == tmp.join(empty))
|
139
|
+
exit! ok
|
140
|
+
end
|
141
|
+
assert_nothing_raised { rd.close }
|
142
|
+
assert_equal(bs * count, IO.writev(wr.fileno, vec))
|
143
|
+
assert_nothing_raised { wr.close }
|
144
|
+
_, status = Process.waitpid2(pid)
|
145
|
+
assert status.success?
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def teardown
|
151
|
+
@fh.close rescue nil
|
152
|
+
@fh = nil
|
153
|
+
File.delete(@file) if File.exists?(@file)
|
154
|
+
end
|
111
155
|
end
|
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: io-extra
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 1
|
7
|
+
- 2
|
8
|
+
- 2
|
9
|
+
version: 1.2.2
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- Daniel J. Berger
|
@@ -9,19 +14,23 @@ autorequire:
|
|
9
14
|
bindir: bin
|
10
15
|
cert_chain: []
|
11
16
|
|
12
|
-
date: 2010-01
|
17
|
+
date: 2010-05-01 00:00:00 -06:00
|
13
18
|
default_executable:
|
14
19
|
dependencies:
|
15
20
|
- !ruby/object:Gem::Dependency
|
16
21
|
name: test-unit
|
17
|
-
|
18
|
-
|
19
|
-
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
24
|
requirements:
|
21
25
|
- - ">="
|
22
26
|
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 2
|
29
|
+
- 0
|
30
|
+
- 3
|
23
31
|
version: 2.0.3
|
24
|
-
|
32
|
+
type: :development
|
33
|
+
version_requirements: *id001
|
25
34
|
description: " Adds the IO.closefrom, IO.fdwalk, IO.pread, IO.pread_ptr, and IO.pwrite\n class methods as well as the IO#directio and IO#directio? instance\n methods (for those platforms that support them).\n"
|
26
35
|
email: djberg96@gmail.com
|
27
36
|
executables: []
|
@@ -34,16 +43,16 @@ extra_rdoc_files:
|
|
34
43
|
- MANIFEST
|
35
44
|
- ext/io/extra.c
|
36
45
|
files:
|
37
|
-
- MANIFEST
|
38
|
-
- examples/example_io_extra.rb
|
39
|
-
- README
|
40
46
|
- CHANGES
|
47
|
+
- doc/io_extra.txt
|
48
|
+
- examples/example_io_extra.rb
|
49
|
+
- ext/extconf.rb
|
50
|
+
- ext/io/extra.c
|
41
51
|
- io-extra.gemspec
|
52
|
+
- MANIFEST
|
42
53
|
- Rakefile
|
54
|
+
- README
|
43
55
|
- test/test_io_extra.rb
|
44
|
-
- doc/io_extra.txt
|
45
|
-
- ext/io/extra.c
|
46
|
-
- ext/extconf.rb
|
47
56
|
has_rdoc: true
|
48
57
|
homepage: http://www.rubyforge.org/projects/shards
|
49
58
|
licenses:
|
@@ -57,18 +66,22 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
57
66
|
requirements:
|
58
67
|
- - ">="
|
59
68
|
- !ruby/object:Gem::Version
|
69
|
+
segments:
|
70
|
+
- 1
|
71
|
+
- 8
|
72
|
+
- 6
|
60
73
|
version: 1.8.6
|
61
|
-
version:
|
62
74
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
63
75
|
requirements:
|
64
76
|
- - ">="
|
65
77
|
- !ruby/object:Gem::Version
|
78
|
+
segments:
|
79
|
+
- 0
|
66
80
|
version: "0"
|
67
|
-
version:
|
68
81
|
requirements: []
|
69
82
|
|
70
83
|
rubyforge_project: shards
|
71
|
-
rubygems_version: 1.3.
|
84
|
+
rubygems_version: 1.3.6
|
72
85
|
signing_key:
|
73
86
|
specification_version: 3
|
74
87
|
summary: Adds extra methods to the IO class.
|