thread_queues 0.0.2 → 0.0.3
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.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/lib/thread_queues/string_buffer.rb +126 -8
- data/spec/thread_queues/string_buffer_spec.rb +122 -23
- data/thread_queues.gemspec +3 -3
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ccec23b5ab55ae4400aee2fe167c800f77f8a92c
|
4
|
+
data.tar.gz: 4949876041f7070682817bb1429cc83264b96630
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c9a5c77bba20b9eb89f9fa96976d4e2483a4146641dbbbed241bbd213b30f7709661cf1fdebfcfa9dc25c1eaf1fc66fb0dadf618efeed6f4ef86dc5b78ac289f
|
7
|
+
data.tar.gz: c2fd0bfa948a3f8c9e32b685ff1f78da6f3a840ae3108d4c9c0bd9af4c99bf0f9f4519504b3b6eef303a4bf60f206582ca145004d868b31d1133920954b223ec
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.3
|
@@ -1,18 +1,34 @@
|
|
1
1
|
require "monitor"
|
2
2
|
|
3
3
|
class ThreadQueues::StringBuffer
|
4
|
+
attr_reader :lineno, :pos
|
5
|
+
|
4
6
|
def initialize(queue)
|
5
7
|
@queue = queue
|
6
8
|
@buffer = ""
|
7
9
|
@mutex = Monitor.new
|
10
|
+
@lineno = 0
|
11
|
+
@pos = 0
|
8
12
|
end
|
9
13
|
|
10
|
-
def gets
|
14
|
+
def gets(sep = "\n", limit = nil)
|
15
|
+
if limit == nil && !sep.is_a?(String)
|
16
|
+
limit = sep
|
17
|
+
sep = "\n"
|
18
|
+
end
|
19
|
+
|
11
20
|
@mutex.synchronize do
|
12
21
|
loop do
|
13
|
-
if match = @buffer.match(/\A(
|
14
|
-
|
15
|
-
|
22
|
+
if match = @buffer.match(/\A([\s\S]+?)#{Regexp.escape(sep)}/)
|
23
|
+
take = match[0]
|
24
|
+
if limit && take.length > limit
|
25
|
+
take = take.slice(0, limit)
|
26
|
+
end
|
27
|
+
|
28
|
+
@buffer.gsub!(/\A#{Regexp.escape(take)}/, "")
|
29
|
+
@lineno += 1
|
30
|
+
@pos += match[0].bytesize
|
31
|
+
return take
|
16
32
|
end
|
17
33
|
|
18
34
|
begin
|
@@ -25,31 +41,121 @@ class ThreadQueues::StringBuffer
|
|
25
41
|
end
|
26
42
|
end
|
27
43
|
|
28
|
-
def
|
44
|
+
def each_line(&blk)
|
45
|
+
with_enumerator(blk) do |y|
|
46
|
+
begin
|
47
|
+
loop do
|
48
|
+
y << gets
|
49
|
+
end
|
50
|
+
rescue EOFError
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def each_char(&blk)
|
56
|
+
with_enumerator(blk) do |y|
|
57
|
+
each_chunk do |chunk|
|
58
|
+
chunk.each_char do |char|
|
59
|
+
y << char
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def each_byte(&blk)
|
66
|
+
with_enumerator(blk) do |y|
|
67
|
+
each_chunk do |chunk|
|
68
|
+
chunk.each_byte do |byte|
|
69
|
+
y << byte
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def read(length = nil, outbuf = nil)
|
76
|
+
return read_all if length == nil
|
77
|
+
|
78
|
+
content = nil
|
79
|
+
|
29
80
|
@mutex.synchronize do
|
30
81
|
loop do
|
31
82
|
if @buffer.length >= length
|
32
|
-
|
83
|
+
content = @buffer.slice!(0, length)
|
84
|
+
@pos += content.bytesize
|
85
|
+
break
|
33
86
|
end
|
34
87
|
|
35
88
|
begin
|
36
89
|
store_more_in_buffer
|
37
90
|
rescue EOFError => e
|
38
|
-
|
39
|
-
|
91
|
+
if @buffer.length > 0
|
92
|
+
content = rest_of_buffer
|
93
|
+
break
|
94
|
+
end
|
95
|
+
|
96
|
+
# Return nil if length is set like a normal IO - otherwise an empty string.
|
97
|
+
if length
|
98
|
+
return nil
|
99
|
+
else
|
100
|
+
content = ""
|
101
|
+
end
|
40
102
|
end
|
41
103
|
end
|
42
104
|
end
|
105
|
+
|
106
|
+
if outbuf
|
107
|
+
outbuf.clear
|
108
|
+
outbuf << content
|
109
|
+
end
|
110
|
+
|
111
|
+
return content
|
112
|
+
end
|
113
|
+
|
114
|
+
def empty?
|
115
|
+
if @pos == 0 && !@closed
|
116
|
+
begin
|
117
|
+
store_more_in_buffer
|
118
|
+
rescue EOFError
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
@pos == 0 && @buffer.empty?
|
43
123
|
end
|
44
124
|
|
45
125
|
private
|
46
126
|
|
127
|
+
def read_all
|
128
|
+
str = ""
|
129
|
+
each_line do |line|
|
130
|
+
str << line
|
131
|
+
end
|
132
|
+
|
133
|
+
return str
|
134
|
+
end
|
135
|
+
|
47
136
|
def rest_of_buffer
|
48
137
|
buffer = @buffer
|
49
138
|
@buffer = ""
|
139
|
+
@pos += buffer.bytesize
|
50
140
|
return buffer
|
51
141
|
end
|
52
142
|
|
143
|
+
def each_chunk
|
144
|
+
begin
|
145
|
+
loop do
|
146
|
+
begin
|
147
|
+
content = @queue.pop.to_s
|
148
|
+
@pos += content.bytesize
|
149
|
+
yield content
|
150
|
+
rescue Exception => e
|
151
|
+
raise EOFError, "No live threads left. Deadlock?" if e.message == "No live threads left. Deadlock?"
|
152
|
+
raise e
|
153
|
+
end
|
154
|
+
end
|
155
|
+
rescue EOFError
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
53
159
|
def store_more_in_buffer
|
54
160
|
@mutex.synchronize do
|
55
161
|
begin
|
@@ -60,4 +166,16 @@ private
|
|
60
166
|
end
|
61
167
|
end
|
62
168
|
end
|
169
|
+
|
170
|
+
def with_enumerator(blk)
|
171
|
+
enum = Enumerator.new do |y|
|
172
|
+
yield(y)
|
173
|
+
end
|
174
|
+
|
175
|
+
if blk
|
176
|
+
enum.each(&blk)
|
177
|
+
else
|
178
|
+
enum
|
179
|
+
end
|
180
|
+
end
|
63
181
|
end
|
@@ -1,8 +1,10 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe ThreadQueues::StringBuffer do
|
4
|
-
|
5
|
-
|
4
|
+
let(:queue) { ThreadQueues::BlockingQueue.new }
|
5
|
+
let(:lines) { lines = ["hello\n", "my\r\n", "name\n", "is kasper\n"] }
|
6
|
+
let(:whole_string) { lines.join("") }
|
7
|
+
let(:string_buffer) {
|
6
8
|
string_buffer = ThreadQueues::StringBuffer.new(queue)
|
7
9
|
|
8
10
|
Thread.new do
|
@@ -17,35 +19,132 @@ describe ThreadQueues::StringBuffer do
|
|
17
19
|
queue.close
|
18
20
|
end
|
19
21
|
|
20
|
-
string_buffer
|
21
|
-
|
22
|
-
string_buffer.gets.should eq "name\n"
|
23
|
-
string_buffer.gets.should eq "is kasper\n"
|
22
|
+
string_buffer
|
23
|
+
}
|
24
24
|
|
25
|
-
|
25
|
+
describe "#gets" do
|
26
|
+
it "returns lines as default" do
|
27
|
+
string_buffer.gets.should eq "hello\n"
|
28
|
+
string_buffer.gets.should eq "my\r\n"
|
29
|
+
string_buffer.gets.should eq "name\n"
|
30
|
+
string_buffer.gets.should eq "is kasper\n"
|
31
|
+
|
32
|
+
expect { string_buffer.gets }.to raise_error(EOFError)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "accepts custom seperators" do
|
36
|
+
string_buffer.gets("\r").should eq "hello\nmy\r"
|
37
|
+
string_buffer.gets("\r").should eq "\nname\nis kasper\n"
|
38
|
+
expect { string_buffer.gets }.to raise_error(EOFError)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "accepts a limit" do
|
42
|
+
string_buffer.gets(3).should eq "hel"
|
43
|
+
string_buffer.gets(10).should eq "lo\n"
|
44
|
+
string_buffer.gets(10).should eq "my\r\n"
|
45
|
+
end
|
46
|
+
|
47
|
+
it "accepts both a limit and a custom seperator" do
|
48
|
+
string_buffer.gets("\r", 3).should eq "hel"
|
49
|
+
string_buffer.gets("\r", 999).should eq "lo\nmy\r"
|
50
|
+
string_buffer.gets("\r", 999).should eq "\nname\nis kasper\n"
|
51
|
+
end
|
26
52
|
end
|
27
53
|
|
28
|
-
|
29
|
-
|
30
|
-
|
54
|
+
describe "#read" do
|
55
|
+
it "with a given length" do
|
56
|
+
string_buffer.read(6).should eq "hello\n"
|
57
|
+
string_buffer.read(4).should eq "my\r\n"
|
58
|
+
string_buffer.read(5).should eq "name\n"
|
59
|
+
string_buffer.read(10).should eq "is kasper\n"
|
31
60
|
|
32
|
-
|
33
|
-
|
61
|
+
expect { string_buffer.gets }.to raise_error(EOFError)
|
62
|
+
end
|
34
63
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
64
|
+
it "reads the whole thing when length is nil" do
|
65
|
+
string_buffer.read.should eq whole_string
|
66
|
+
end
|
67
|
+
|
68
|
+
it "supports outbuf argument" do
|
69
|
+
outbuf = "kasper"
|
70
|
+
string_buffer.read(6, outbuf).should eq "hello\n"
|
71
|
+
outbuf.should eq "hello\n"
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should return the correct values when it has reaches eof" do
|
75
|
+
string_buffer.read.should eq whole_string
|
76
|
+
string_buffer.read.should eq ""
|
77
|
+
string_buffer.read(5).should eq nil
|
42
78
|
end
|
79
|
+
end
|
80
|
+
|
81
|
+
it "#each_line" do
|
82
|
+
count = 0
|
83
|
+
string_buffer.each_line do |line|
|
84
|
+
line.should eq lines[count]
|
85
|
+
count += 1
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
it "#each_char" do
|
90
|
+
count = 0
|
91
|
+
string_buffer.each_char do |char|
|
92
|
+
char.should eq whole_string.slice(count, 1)
|
93
|
+
count += 1
|
94
|
+
end
|
95
|
+
|
96
|
+
string_buffer.pos.should eq 25
|
97
|
+
end
|
98
|
+
|
99
|
+
it "#each_byte" do
|
100
|
+
count = 0
|
101
|
+
string_buffer.each_byte do |byte|
|
102
|
+
byte.should eq whole_string.bytes[count]
|
103
|
+
count += 1
|
104
|
+
end
|
105
|
+
|
106
|
+
string_buffer.pos.should eq 25
|
107
|
+
end
|
43
108
|
|
44
|
-
|
45
|
-
string_buffer.
|
46
|
-
|
47
|
-
string_buffer.
|
109
|
+
it "#lineno" do
|
110
|
+
string_buffer.lineno.should eq 0
|
111
|
+
|
112
|
+
string_buffer.gets
|
113
|
+
string_buffer.lineno.should eq 1
|
114
|
+
|
115
|
+
string_buffer.gets
|
116
|
+
string_buffer.lineno.should eq 2
|
117
|
+
|
118
|
+
string_buffer.gets
|
119
|
+
string_buffer.lineno.should eq 3
|
120
|
+
|
121
|
+
string_buffer.gets
|
122
|
+
string_buffer.lineno.should eq 4
|
48
123
|
|
49
124
|
expect { string_buffer.gets }.to raise_error(EOFError)
|
125
|
+
string_buffer.lineno.should eq 4
|
126
|
+
end
|
127
|
+
|
128
|
+
it "#pos" do
|
129
|
+
string_buffer.pos.should eq 0
|
130
|
+
string_buffer.gets
|
131
|
+
string_buffer.pos.should eq 6
|
132
|
+
string_buffer.read(4)
|
133
|
+
string_buffer.pos.should eq 10
|
134
|
+
string_buffer.read(999)
|
135
|
+
string_buffer.pos.should eq 25
|
136
|
+
end
|
137
|
+
|
138
|
+
describe "#empty?" do
|
139
|
+
it "returns false when empty" do
|
140
|
+
string_buffer.empty?.should eq false
|
141
|
+
end
|
142
|
+
|
143
|
+
it "returns true when not empty" do
|
144
|
+
queue = ThreadQueues::BlockingQueue.new
|
145
|
+
sbuffer = ThreadQueues::StringBuffer.new(queue)
|
146
|
+
queue.close
|
147
|
+
sbuffer.empty?.should eq true
|
148
|
+
end
|
50
149
|
end
|
51
150
|
end
|
data/thread_queues.gemspec
CHANGED
@@ -2,16 +2,16 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: thread_queues 0.0.
|
5
|
+
# stub: thread_queues 0.0.3 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "thread_queues"
|
9
|
-
s.version = "0.0.
|
9
|
+
s.version = "0.0.3"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib"]
|
13
13
|
s.authors = ["kaspernj"]
|
14
|
-
s.date = "2014-12-
|
14
|
+
s.date = "2014-12-09"
|
15
15
|
s.description = "Do thread-related work with BlockingQueue and BufferedQueue in Ruby."
|
16
16
|
s.email = "k@spernj.org"
|
17
17
|
s.extra_rdoc_files = [
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: thread_queues
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- kaspernj
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-12-
|
11
|
+
date: 2014-12-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: string-cases
|