qio 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ coverage/*
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use 1.9.3@qio --create
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in qio.gemspec
4
+ gemspec
@@ -0,0 +1,12 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'bundler/setup'
4
+ Bundler.require(:default)
5
+
6
+ Dir['tasks/*.rake'].sort.each { |task| load task }
7
+
8
+ # Add rake tasks from selected gems
9
+ gem_names = []
10
+ gem_names.each do |gem_name|
11
+ Dir[File.join(Gem.searcher.find(gem_name).full_gem_path, '**', '*.rake')].each{|rake_file| load rake_file }
12
+ end
@@ -0,0 +1,4 @@
1
+ require "thread"
2
+ require "qio/version"
3
+ require "qio/base_io"
4
+ require "qio/queued_input_io"
@@ -0,0 +1,605 @@
1
+ require 'thread'
2
+
3
+ module QIO
4
+
5
+ # Classes that want to mimic IO can acqire much of its functionality simply
6
+ # by including this module and over-riding the following methods:
7
+ #
8
+ # close
9
+ # closed?
10
+ # eof?
11
+ # sysread(maxlen, outbuf=nil)
12
+ # sysseek(offset, whence=IO::SEEK_SET)
13
+ # syswrite(string)
14
+ #
15
+ # The following methds are not provided. If you know what you're doing, and
16
+ # you know that you're going to need it, you may also over-ride:
17
+ #
18
+ # autoclose=(bool)
19
+ # autoclose?
20
+ # close_on_exec=(bool)
21
+ # close_on_exec?
22
+ # close_read
23
+ # close_write
24
+ # fcntl(integer_cmd, arg)
25
+ # fileno
26
+ # flush
27
+ # fsync
28
+ # ioctl(integer_cmd, arg)
29
+ # pid
30
+ # reopen(other_io_or_path, mode_str=nil)
31
+ # stat
32
+ # sync
33
+ # sync=(bool)
34
+ # ungetbyte(string_or_integer)
35
+ # ungetc(string)
36
+ #
37
+ # You get all the following for free, but if that's not good enough for you,
38
+ # and you're sure you can do better, you may over-ride:
39
+ #
40
+ # <<(obj)
41
+ # advise(advice, offset=0, len=0)
42
+ # binmode #TODO!
43
+ # binmode? #TODO!
44
+ # bytes
45
+ # chars
46
+ # codepoints
47
+ # each
48
+ # each_byte
49
+ # each_char
50
+ # each_codepoint
51
+ # each_line
52
+ # eof
53
+ # external_encoding #TODO!
54
+ # fdatasync
55
+ # getbyte
56
+ # getc #TODO!
57
+ # gets(sep=$/, limit=nil)
58
+ # internal_encoding #TODO!
59
+ # isatty
60
+ # lineno
61
+ # lineno=(lineno)
62
+ # lines(sep=$/, limit=nil)
63
+ # pos
64
+ # pos=(pos)
65
+ # print(*args)
66
+ # printf(format_string, *args)
67
+ # putc(obj)
68
+ # puts(*args)
69
+ # read(length=nil, buffer=nil)
70
+ # read_nonblock(maxlen, outbuf=nil)
71
+ # readbyte
72
+ # reachar
73
+ # readline(sep=$/, limit=nil)
74
+ # readlines(sep=$/, limit=nil)
75
+ # readpartial(maxlen, outbuf=nil)
76
+ # rewind
77
+ # seek(amount, whence=IO::SEEK_SET)
78
+ # set_encoding(ext_enc, int_enc=nil, opt=nil) #TODO!
79
+ # tell
80
+ # to_i # if you defined fileno
81
+ # tty?
82
+ # write(string)
83
+ # write_nonblock(string)
84
+ #
85
+ module BaseIO
86
+
87
+ # Implementation relies on: write
88
+ def <<(obj)
89
+ write(obj.to_s)
90
+ self
91
+ end
92
+
93
+ # No-op
94
+ def advise(advice, offset=0, len=0); end
95
+
96
+ # NotImplementedError
97
+ def autoclose=(bool)
98
+ raise NotImplementedError
99
+ end
100
+
101
+ # NotImplementedError
102
+ def autoclose?
103
+ raise NotImplementedError
104
+ end
105
+
106
+ # TODO: Implement binmode.
107
+ def binmode
108
+ end
109
+
110
+ # TODO: Implement: binmode?
111
+ def binmode?
112
+ true
113
+ end
114
+
115
+ # Implementation relies on: getbyte
116
+ def bytes
117
+ return to_enum :bytes unless block_given?
118
+ while b = getbyte
119
+ yield b
120
+ end
121
+ end
122
+ alias :each_byte :bytes
123
+
124
+ # Implementation relies on: getc
125
+ def chars
126
+ return to_enum :chars unless block_given?
127
+ while c = getc
128
+ yield c
129
+ end
130
+ end
131
+ alias :each_char :chars
132
+
133
+ # Over-ride me!
134
+ def close
135
+ raise NotImplementedError, "Subclass should over-ride!"
136
+ end
137
+
138
+ # NotImplementedError
139
+ def close_on_exec=(bool)
140
+ raise NotImplementedError
141
+ end
142
+
143
+ # NotImplementedError
144
+ def close_on_exec?
145
+ raise NotImplementedError
146
+ end
147
+
148
+ # NotImplementedError
149
+ def close_read
150
+ raise NotImplementedError
151
+ end
152
+
153
+ # NotImplementedError
154
+ def close_write
155
+ raise NotImplementedError
156
+ end
157
+
158
+ # Over-ride me!
159
+ def closed?
160
+ raise NotImplementedError, "Subclass should over-ride!"
161
+ end
162
+
163
+ # Implementation relies on: getc
164
+ def codepoints
165
+ return to_enum :codepoints unless block_given?
166
+ while c = getc
167
+ c.codepoints.each do |cp|
168
+ yield cp
169
+ end
170
+ end
171
+ end
172
+ alias :each_codepoint :codepoints
173
+
174
+ # Over-ride me!
175
+ def eof?
176
+ raise NotImplementedError, "Subclass should over-ride!"
177
+ end
178
+ alias :eof :eof?
179
+
180
+ # TODO: Implement external_encoding
181
+ def external_encoding
182
+ raise NotImplementedError
183
+ end
184
+
185
+ # NotImplementedError
186
+ def fcntl(integer_cmd, arg)
187
+ raise NotImplementedError
188
+ end
189
+
190
+ # Implementation relies on: fsync
191
+ def fdatasync
192
+ fsync
193
+ end
194
+
195
+ # NotImplementedError
196
+ def fileno
197
+ raise NotImplementedError
198
+ end
199
+ alias :to_i :fileno
200
+
201
+ # NotImplementedError
202
+ def flush
203
+ raise NotImplementedError
204
+ end
205
+
206
+ # NotImplementedError
207
+ def fsync
208
+ raise NotImplementedError
209
+ end
210
+
211
+ # Implementation relies on: read
212
+ def getbyte
213
+ read(1)
214
+ end
215
+
216
+ # TODO: Implement getc (probably need to know about encoding conversions first)
217
+ def getc
218
+ raise NotImplementedError
219
+ end
220
+
221
+ # Implementation relies on: getc
222
+ # TODO: Maybe it should rely on getbyte instead, so we don't read too many bytes on accident.
223
+ def gets(sep=$/, limit=nil)
224
+ return nil if eof?
225
+ if limit.nil? && sep.is_a?(Integer) #TODO: compare this logic with ::IO#getc
226
+ limit = sep.to_i
227
+ sep = $/
228
+ end
229
+ if !limit.nil? && limit < 0
230
+ raise ArgumentError, ('negative limit %1d given' % limit)
231
+ end
232
+ sep = "\n\n" if sep == ""
233
+ line = ""
234
+ while (c = getc)
235
+ line << c
236
+ break if !sep.nil? && line.end_with?(sep)
237
+ break if !limit.nil? && line.bytesize >= limit
238
+ end
239
+ if !limit.nil? && limit >= 0 && line.bytesize > limit
240
+ leftovers = line.byteslice(limit .. -1) #TODO: what should we do with this?
241
+ line = line.byteslice(0,limit)
242
+ end
243
+ $. = (lineno += 1)
244
+ $_ = line
245
+ end
246
+
247
+ # TODO: Implement internal_encoding
248
+ def internal_encoding
249
+ raise NotImplementedError
250
+ end
251
+
252
+ # NotImplementedError
253
+ def ioctl(integer_cmd, arg)
254
+ raise NotImplementedError
255
+ end
256
+
257
+ # Always returns false
258
+ def isatty
259
+ false
260
+ end
261
+ alias :tty? :isatty
262
+
263
+ # Implementation relies on gets to properly keep this up-to-date.
264
+ def lineno
265
+ @lineno || uninitialized!
266
+ end
267
+
268
+ def lineno=(lineno)
269
+ @lineno = lineno
270
+ end
271
+
272
+ # Implementation relies on: gets
273
+ def lines(sep=$/, limit=nil)
274
+ return to_enum :lines unless block_given?
275
+ while s = gets
276
+ yield s
277
+ end
278
+ end
279
+ alias :each :lines
280
+ alias :each_line :lines
281
+
282
+ # NotImplementedError
283
+ def pid
284
+ raise NotImplementedError
285
+ end
286
+
287
+ # Subclass is responsible for keeping pos up-to-date!
288
+ def pos
289
+ @pos || uninitialized!
290
+ end
291
+ alias :tell :pos
292
+
293
+ # Subclass is responsible for keeping pos up-to-date!
294
+ def pos=(pos)
295
+ @pos = pos
296
+ end
297
+
298
+ # Implementation relies on write.
299
+ def print(*args)
300
+ args = [$_] if args.size == 0
301
+ first_one = true
302
+ args.each do |obj|
303
+ write(obj.to_s)
304
+ write($,) unless first_one || $,.nil?
305
+ first_one = false
306
+ end
307
+ write($\) unless $\.nil?
308
+ nil
309
+ end
310
+
311
+ # Implementation relies on print.
312
+ def printf(format_string, *args)
313
+ print(Kernel.sprintf(format_string, *args))
314
+ end
315
+
316
+ # Implementation relies on write.
317
+ def putc(obj)
318
+ if obj.is_a?(Numeric)
319
+ write((obj.to_i & 0xff).chr)
320
+ else
321
+ write(obj.to_s.byteslice(0))
322
+ end
323
+ end
324
+
325
+ def puts(*args)
326
+ if args.size == 0
327
+ write("\n")
328
+ else
329
+ args.flatten.each do |line|
330
+ line = line.to_s
331
+ write(line)
332
+ write("\n") unless line.end_with?("\n")
333
+ end
334
+ end
335
+ nil
336
+ end
337
+
338
+ def read(length=nil, buffer=nil)
339
+ if !length.nil? && length < 0
340
+ raise ArgumentError, ('negative length %1d given' % length)
341
+ end
342
+
343
+ buffer = buffer.nil? ? "" : buffer.replace("")
344
+ if length.nil?
345
+ begin
346
+ buffer << readpartial until eof?
347
+ rescue EOFError
348
+ end
349
+ # TODO: Apply encoding conversion to buffer.
350
+ buffer
351
+ elsif length == 0
352
+ buffer
353
+ else
354
+ begin
355
+ while buffer.bytesize < length && !eof?
356
+ buffer << readpartial(length - buffer.bytesize)
357
+ # TODO: Code Review - result should be ASCII-8BIT. Is it?
358
+ end
359
+ rescue EOFError
360
+ end
361
+ buffer.empty? ? nil : buffer
362
+ end
363
+ end
364
+
365
+ def read_nonblock(maxlen, outbuf=nil)
366
+ nonblock_readable do
367
+ sysread(maxlen, outbuff)
368
+ end
369
+ end
370
+
371
+ # Implementation relies on getbyte
372
+ def readbyte
373
+ getbyte || raise(EOFError)
374
+ end
375
+
376
+ # Implementation relies on: getc
377
+ def readchar
378
+ getc || raise(EOFError)
379
+ end
380
+
381
+ # Implementation relies on: gets
382
+ def readline(sep=$/, limit=nil)
383
+ gets(sep, limit) || raise(EOFError)
384
+ end
385
+
386
+ # Implementation relies on: gets
387
+ def readlines(sep=$/, limit=nil)
388
+ result = []
389
+ loop do
390
+ if (line = gets(sep, limit))
391
+ break
392
+ else
393
+ result << line
394
+ end
395
+ end
396
+ result
397
+ end
398
+
399
+ # Implementation relies on: read_nonblock
400
+ def readpartial(maxlen, outbuf=nil)
401
+ read_nonblock(maxlen, outbuf)
402
+ rescue IO::WaitReadable
403
+ block_until_readable
404
+ retry
405
+ end
406
+
407
+ # NotImplementedError
408
+ def reopen(other_io_or_path, mode_str=nil)
409
+ raise NotImplementedError
410
+ end
411
+
412
+ # Implementation relies on: seek
413
+ def rewind
414
+ seek(0)
415
+ end
416
+
417
+ # Implementation relies on: sysseek
418
+ def seek(amount, whence=IO::SEEK_SET)
419
+ sysseek(amount, whence)
420
+ end
421
+
422
+ # TODO: Implement set_encoding
423
+ def set_encoding(ext_enc, int_enc=nil, opt=nil)
424
+ raise NotImplementedError
425
+ end
426
+
427
+ # NotImplementedError
428
+ def stat
429
+ raise NotImplementedError
430
+ end
431
+
432
+ # NotImplementedError
433
+ def sync
434
+ raise NotImplementedError
435
+ end
436
+
437
+ # NotImplementedError
438
+ def sync=(bool)
439
+ raise NotImplementedError
440
+ end
441
+
442
+ # Over-ride me!
443
+ # Remember to count *bytes*, not chars.
444
+ # Remember to update pos.
445
+ # Remember to use consume_readable to wrap the atomic part of your update.
446
+ def sysread(maxlen, outbuf=nil)
447
+ raise NotImplementedError
448
+ end
449
+
450
+ # Over-ride me!
451
+ # Remember to count *bytes*, not chars.
452
+ # Remember to update pos.
453
+ def sysseek(offset, whence=IO::SEEK_SET)
454
+ raise NotImplementedError # TODO: provide best-effort implementation for sysseek
455
+ end
456
+
457
+ # Over-ride me!
458
+ # Remember to count *bytes*, not chars.
459
+ # Remember to update pos.
460
+ # Remember to use consume_writable to wrap the atomic part of your update.
461
+ def syswrite(string)
462
+ raise NotImplementedError
463
+ end
464
+
465
+ # NotImplementedError
466
+ def ungetbyte(string_or_integer)
467
+ raise NotImplementedError
468
+ end
469
+
470
+ # NotImplementedError
471
+ def ungetc(string)
472
+ raise NotImplementedError
473
+ end
474
+
475
+ # Implementation relies on: write_nonblock
476
+ def write(string)
477
+ written = 0
478
+ length = string.bytesize
479
+ while written < length
480
+ begin
481
+ written += write_nonblock(string.byteslice(written, length - written))
482
+ rescue IO::WaitWritable, Errno::EINTR
483
+ block_until_writable
484
+ retry
485
+ end
486
+ end
487
+ written
488
+ end
489
+
490
+ # Implementation relies on: syswrite
491
+ def write_nonblock(string)
492
+ nonblock_writable do
493
+ syswrite(string)
494
+ end
495
+ end
496
+
497
+ protected
498
+
499
+ # Subclass should call super in initialize
500
+ def initialize(*args, &callback)
501
+ super(*args, &callback)
502
+ @pos = 0
503
+ @lineno = 0
504
+ @mutex = Mutex.new
505
+ @readable_resource = ConditionVariable.new
506
+ @writable_resource = ConditionVariable.new
507
+ @nonblock_readable = false
508
+ @nonblock_writable = false
509
+ end
510
+
511
+ # Subclass should call me as appropriate. I'll take care of waking threads.
512
+ # Your callback must:
513
+ # * Be quick, you're inside a critical section!
514
+ # * Return true if it's safe to do a non-blocking read, false otherwise.
515
+ def consume_readable(&callback)
516
+ synchronize do
517
+ bool = callback.call
518
+ if @nonblock_readable != bool
519
+ @nonblock_readable = bool
520
+ readable_resource.signal
521
+ end
522
+ end
523
+ end
524
+
525
+ # Subclass should call me as appropriate. I'll take care of waking threads.
526
+ # Your callback must:
527
+ # * Be quick, you're inside a critical section!
528
+ # * Return true if it's safe to do a non-blocking write, false otherwise.
529
+ def consume_writable(&callback)
530
+ synchronize do
531
+ bool = callback.call
532
+ if @nonblock_writable != bool
533
+ @nonblock_writable = bool
534
+ writable_resource.signal
535
+ end
536
+ end
537
+ end
538
+
539
+ alias :provide_readable :consume_readable
540
+ alias :provide_writable :consume_writable
541
+
542
+ private
543
+
544
+ def uninitialized!
545
+ raise "Subclass did not call super in its initialize method!"
546
+ end
547
+
548
+ def mutex
549
+ @mutex || uninitialized!
550
+ end
551
+
552
+ def readable_resource
553
+ @readable_resource || uninitialized!
554
+ end
555
+
556
+ def writable_resource
557
+ @writable_resource || uninitialized!
558
+ end
559
+
560
+ # Don't call this unless you know what you're doing!
561
+ def synchronize
562
+ mutex.synchronize do
563
+ yield
564
+ end
565
+ end
566
+
567
+ def block_until_readable(&callback)
568
+ loop do
569
+ synchronize do
570
+ return if @nonblock_readable
571
+ readable_resource.wait(mutex)
572
+ end
573
+ end
574
+ end
575
+
576
+ def block_until_writable
577
+ loop do
578
+ synchronize do
579
+ return if @nonblock_writable
580
+ writable_resource.wait(mutex)
581
+ end
582
+ end
583
+ end
584
+
585
+ def nonblock_readable(&callback)
586
+ synchronize do
587
+ if @nonblock_readable
588
+ callback.call
589
+ else
590
+ raise(IO::WaitReadable, "read would block")
591
+ end
592
+ end
593
+ end
594
+
595
+ def nonblock_writable(&callback)
596
+ synchronize do
597
+ if @nonblock_writable
598
+ callback.call
599
+ else
600
+ raise(IO::WaitWritable, "write would block")
601
+ end
602
+ end
603
+ end
604
+ end
605
+ end
@@ -0,0 +1,91 @@
1
+ module QIO
2
+ class QueuedInputIO
3
+ include BaseIO
4
+ def initialize
5
+ super
6
+ @deque = [] #TODO: Consider using a real deque.
7
+ @eof = false
8
+ @closed = false
9
+ @queued_eof = false
10
+ end
11
+
12
+ def close
13
+ assert_open
14
+ synchronize do
15
+ @closed = true
16
+ @deque.clear
17
+ @deque = nil
18
+ end
19
+ end
20
+
21
+ def closed?
22
+ @closed
23
+ end
24
+
25
+ def eof?
26
+ assert_open
27
+ @eof ||= (@queued_eof && @deque.length <= 1)
28
+ end
29
+
30
+ def sysread(maxlen, outbuf=nil)
31
+ q = @deque
32
+ raise EOFError if eof?
33
+ outbuf ||= ""
34
+ consume_readable do
35
+ raise EOFError if eof?
36
+ data = @deque.shift
37
+ raise SystemCallError if data.nil? || data.empty?
38
+ if data.bytesize <= maxlen
39
+ outbuf.replace(data)
40
+ pos += outbuf.bytesize
41
+ else
42
+ outbuf.replace(data.byteslice(0, maxlen))
43
+ @deque.unshift(data.byteslice(maxlen .. -1))
44
+ pos += maxlen
45
+ end
46
+ @deque.any?
47
+ end
48
+ outbuf
49
+ end
50
+
51
+ def sysseek(offset, whence=IO::SEEK_SET)
52
+ # TODO: Implement (best-effort) sysseek
53
+ end
54
+
55
+ def add_input(string)
56
+ raise(ArgumentError, 'input must be a string') unless string.is_a?(String)
57
+ assert_open
58
+ assert_accepting_input
59
+ return self if string.empty?
60
+ provide_readable do
61
+ assert_open
62
+ assert_accepting_input
63
+ @deque.push(string)
64
+ true
65
+ end
66
+ self
67
+ end
68
+
69
+ def end_input!
70
+ return self if @queued_eof
71
+ provide_readable do
72
+ unless @queued_eof
73
+ @deque.push(:eof)
74
+ @queued_eof = true
75
+ end
76
+ true
77
+ end
78
+ self
79
+ end
80
+
81
+ private
82
+
83
+ def assert_open
84
+ raise(IOError, "stream is closed!") if @closed
85
+ end
86
+
87
+ def assert_accepting_input
88
+ raise(IOError, "stream was ended!") if @queued_eof
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,3 @@
1
+ module QIO
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "qio/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "qio"
7
+ s.version = QIO::VERSION
8
+ s.authors = ["Chris Johnson"]
9
+ s.email = ["chris@kindkid.com"]
10
+ s.homepage = "https://github.com/kindkid/qio"
11
+ s.summary = "IO facade, backed by a queue."
12
+ s.description = s.summary
13
+
14
+ s.rubyforge_project = "qio"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_development_dependency "rspec", "~> 2.9.0"
22
+ s.add_development_dependency "simplecov", "~> 0.6.1"
23
+ s.add_development_dependency("rb-fsevent", "~> 0.9.0") if RUBY_PLATFORM =~ /darwin/i
24
+ s.add_development_dependency "guard", "~> 1.0.1"
25
+ s.add_development_dependency "guard-bundler", "~> 0.1.3"
26
+ s.add_development_dependency "guard-rspec", "~> 0.6.0"
27
+ end
@@ -0,0 +1,5 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe QIO do
4
+ it "should have some specs"
5
+ end
@@ -0,0 +1,7 @@
1
+ require 'simplecov'
2
+ SimpleCov.start
3
+
4
+ require 'rubygems'
5
+ require 'bundler'
6
+
7
+ Bundler.require(:default, :test, :development)
@@ -0,0 +1,5 @@
1
+ desc "Open development console"
2
+ task :console do
3
+ puts "Loading development console..."
4
+ system "irb -r #{File.join('.', 'lib', 'qio')}"
5
+ end
@@ -0,0 +1,10 @@
1
+ desc "Generate and open coverage report"
2
+ task :coverage do
3
+ system 'rake spec'
4
+ system 'open coverage/index.html'
5
+ end
6
+
7
+ desc "Generate and open coverage report"
8
+ task :rcov do
9
+ system 'rake coverage'
10
+ end
@@ -0,0 +1,4 @@
1
+ desc "Load the environment"
2
+ task :environment do
3
+ require File.expand_path('../../lib/qio', __FILE__)
4
+ end
@@ -0,0 +1,12 @@
1
+ require 'rspec/core/rake_task'
2
+
3
+ desc "Run all specs"
4
+ RSpec::Core::RakeTask.new(:spec) do |t|
5
+ t.rspec_opts = [
6
+ '-c',
7
+ '--format documentation',
8
+ '-r ./spec/spec_helper.rb',
9
+ '--backtrace'
10
+ ]
11
+ t.pattern = 'spec/**/*_spec.rb'
12
+ end
metadata ADDED
@@ -0,0 +1,134 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: qio
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Chris Johnson
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-03-24 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: &70139110710660 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 2.9.0
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *70139110710660
25
+ - !ruby/object:Gem::Dependency
26
+ name: simplecov
27
+ requirement: &70139110710020 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: 0.6.1
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *70139110710020
36
+ - !ruby/object:Gem::Dependency
37
+ name: rb-fsevent
38
+ requirement: &70139110709260 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 0.9.0
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70139110709260
47
+ - !ruby/object:Gem::Dependency
48
+ name: guard
49
+ requirement: &70139110708540 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 1.0.1
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *70139110708540
58
+ - !ruby/object:Gem::Dependency
59
+ name: guard-bundler
60
+ requirement: &70139110707940 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ~>
64
+ - !ruby/object:Gem::Version
65
+ version: 0.1.3
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *70139110707940
69
+ - !ruby/object:Gem::Dependency
70
+ name: guard-rspec
71
+ requirement: &70139110663080 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ~>
75
+ - !ruby/object:Gem::Version
76
+ version: 0.6.0
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: *70139110663080
80
+ description: IO facade, backed by a queue.
81
+ email:
82
+ - chris@kindkid.com
83
+ executables: []
84
+ extensions: []
85
+ extra_rdoc_files: []
86
+ files:
87
+ - .gitignore
88
+ - .rvmrc
89
+ - Gemfile
90
+ - Rakefile
91
+ - lib/qio.rb
92
+ - lib/qio/base_io.rb
93
+ - lib/qio/queued_input_io.rb
94
+ - lib/qio/version.rb
95
+ - qio.gemspec
96
+ - spec/lib/qio_spec.rb
97
+ - spec/spec_helper.rb
98
+ - tasks/console.rake
99
+ - tasks/coverage.rake
100
+ - tasks/environment.rake
101
+ - tasks/spec.rake
102
+ homepage: https://github.com/kindkid/qio
103
+ licenses: []
104
+ post_install_message:
105
+ rdoc_options: []
106
+ require_paths:
107
+ - lib
108
+ required_ruby_version: !ruby/object:Gem::Requirement
109
+ none: false
110
+ requirements:
111
+ - - ! '>='
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ segments:
115
+ - 0
116
+ hash: -222388549614253970
117
+ required_rubygems_version: !ruby/object:Gem::Requirement
118
+ none: false
119
+ requirements:
120
+ - - ! '>='
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ segments:
124
+ - 0
125
+ hash: -222388549614253970
126
+ requirements: []
127
+ rubyforge_project: qio
128
+ rubygems_version: 1.8.10
129
+ signing_key:
130
+ specification_version: 3
131
+ summary: IO facade, backed by a queue.
132
+ test_files:
133
+ - spec/lib/qio_spec.rb
134
+ - spec/spec_helper.rb