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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c6ca817b3ff688ca8b86e3999a607c3df3b1303e
4
- data.tar.gz: df412baf2c93ed8012664f669948277e01b45169
3
+ metadata.gz: ccec23b5ab55ae4400aee2fe167c800f77f8a92c
4
+ data.tar.gz: 4949876041f7070682817bb1429cc83264b96630
5
5
  SHA512:
6
- metadata.gz: c5b7b8fdfda30821ab583c5eaf9a518876aa85b80795cd85430c355a93c7a914d545e0639697ed9a972d8f1cfcde4f33d420cff2256bdfa639288a5a729745fd
7
- data.tar.gz: 3828274cd1da77a1d9f2209c75eaf44a0a16aefc697b90f3603149ba2b9cb586716677a3b8743c08b22b22d85ab819853b284f85ce3fc71cc4fa94bf54d4dae1
6
+ metadata.gz: c9a5c77bba20b9eb89f9fa96976d4e2483a4146641dbbbed241bbd213b30f7709661cf1fdebfcfa9dc25c1eaf1fc66fb0dadf618efeed6f4ef86dc5b78ac289f
7
+ data.tar.gz: c2fd0bfa948a3f8c9e32b685ff1f78da6f3a840ae3108d4c9c0bd9af4c99bf0f9f4519504b3b6eef303a4bf60f206582ca145004d868b31d1133920954b223ec
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.2
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(.+)\n/)
14
- @buffer.gsub!(/\A(.+)\n/, "")
15
- return match[0]
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 read(length)
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
- return @buffer.slice!(0, length)
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
- return rest_of_buffer if @buffer.length > 0
39
- raise e
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
- it "works with gets" do
5
- queue = ThreadQueues::BlockingQueue.new
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.gets.should eq "hello\n"
21
- string_buffer.gets.should eq "my\r\n"
22
- string_buffer.gets.should eq "name\n"
23
- string_buffer.gets.should eq "is kasper\n"
22
+ string_buffer
23
+ }
24
24
 
25
- expect { string_buffer.gets }.to raise_error(EOFError)
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
- it "should read the right lengths" do
29
- queue = ThreadQueues::BufferedQueue.new(5)
30
- string_buffer = ThreadQueues::StringBuffer.new(queue)
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
- Thread.new do
33
- Thread.current.abort_on_exception = true
61
+ expect { string_buffer.gets }.to raise_error(EOFError)
62
+ end
34
63
 
35
- queue.push("hel")
36
- queue.push("lo\n")
37
- queue.push("my\r\n")
38
- queue.push("nam")
39
- queue.push("e\n")
40
- queue.push("is kasper\n")
41
- queue.close
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
- string_buffer.read(6).should eq "hello\n"
45
- string_buffer.read(4).should eq "my\r\n"
46
- string_buffer.read(5).should eq "name\n"
47
- string_buffer.read(10).should eq "is kasper\n"
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
@@ -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.2 ruby lib
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.2"
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-07"
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.2
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-07 00:00:00.000000000 Z
11
+ date: 2014-12-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: string-cases