em-files 0.1.1 → 0.2.0

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.
Files changed (5) hide show
  1. data/README.md +31 -0
  2. data/VERSION +1 -1
  3. data/em-files.gemspec +2 -2
  4. data/lib/em-files.rb +113 -18
  5. metadata +3 -3
data/README.md CHANGED
@@ -26,6 +26,37 @@ methods only, so for special operations use simply:
26
26
  EM::File::open("some_file.txt", "r") do |io|
27
27
  io.native # returns native Ruby File class object
28
28
  end
29
+
30
+ ### Special Uses
31
+
32
+ It's possible to use also another IO objects than `File` object by
33
+ giving appropriate IO instance instead of filename to methods:
34
+
35
+ require "em-files"
36
+ require "stringio"
37
+
38
+ io = StringIO::new
39
+
40
+ EM::run do
41
+ EM::File::open(io) do |io|
42
+ # some multiplexed operations
43
+ end
44
+ end
45
+
46
+ By this way you can also perform for example more time consuming
47
+ operations by simple way (if they can be processed in block manner)
48
+ using filters:
49
+
50
+ require "em-files"
51
+ require "zlib"
52
+
53
+ zip = Zlib::Deflate::new
54
+ filter = Proc::new { |chunk| zip.deflate(chunk, Zlib::SYNC_FLUSH) }
55
+ data = "..." # some bigger than big data
56
+
57
+ EM::run do
58
+ EM::File::write(data, filter) # done in several ticks
59
+ end
29
60
 
30
61
 
31
62
  Contributing
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.1
1
+ 0.2.0
data/em-files.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{em-files}
8
- s.version = "0.1.1"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Martin Kozák"]
12
- s.date = %q{2011-03-09}
12
+ s.date = %q{2011-03-19}
13
13
  s.email = %q{martinkozak@martinkozak.net}
14
14
  s.extra_rdoc_files = [
15
15
  "LICENSE.txt",
data/lib/em-files.rb CHANGED
@@ -15,6 +15,12 @@ module EM
15
15
  #
16
16
 
17
17
  class File
18
+
19
+ ##
20
+ # Holds the default size of block operated during one tick.
21
+ #
22
+
23
+ RWSIZE = 65536
18
24
 
19
25
  ##
20
26
  # Opens the file.
@@ -31,7 +37,9 @@ module EM
31
37
  # @return [File] file access object
32
38
  #
33
39
 
34
- def self.open(filepath, mode = "r", rwsize = 65536, &block) # 64 kilobytes
40
+ def self.open(filepath, mode = "r", rwsize = self::RWSIZE, &block) # 64 kilobytes
41
+ rwsize = self::RWSIZE if rwsize.nil?
42
+
35
43
  file = self::new(filepath, mode, rwsize)
36
44
  if not block.nil?
37
45
  block.call(file)
@@ -42,38 +50,47 @@ module EM
42
50
 
43
51
  ##
44
52
  # Reads whole content of the file. Be warn, it reads it in
45
- # binary mode.
53
+ # binary mode. If IO object is given instead of filepath, uses
54
+ # it as native one and +mode+ argument is ignored.
46
55
  #
47
56
  # @param [String] filepath path to file
48
57
  # @param [Integer] rwsize size of block operated during one tick
58
+ # @param [Proc] filter filter which for postprocessing each
59
+ # read chunk
49
60
  # @param [Proc] block block for giving back the result
50
61
  #
51
62
 
52
63
 
53
- def self.read(filepath, rwsize = 65536, &block)
64
+ def self.read(filepath, rwsize = self::RWSIZE, filter = nil, &block)
65
+ rwsize = self::RWSIZE if rwsize.nil?
54
66
  self::open(filepath, "rb", rwsize) do |io|
55
- io.read do |out|
56
- block.call(out)
67
+ io.read(nil, filter) do |out|
57
68
  io.close()
69
+ block.call(out)
58
70
  end
59
71
  end
60
72
  end
61
73
 
62
74
  ##
63
- # Writes data to file and closes it. Writes them in binary mode.
75
+ # Writes data to file and closes it. Writes them in binary mode.
76
+ # If IO object is given instead of filepath, uses it as native
77
+ # one and +mode+ argument is ignored.
64
78
  #
65
79
  # @param [String] filepath path to file
66
80
  # @param [String] data data for write
67
81
  # @param [Integer] rwsize size of block operated during one tick
82
+ # @param [Proc] filter filter which for preprocessing each
83
+ # written chunk
68
84
  # @param [Proc] block block called when writing is finished with
69
85
  # written bytes size count as parameter
70
86
  #
71
87
 
72
- def self.write(filepath, data = "", rwsize = 65536, &block)
88
+ def self.write(filepath, data = "", rwsize = self::RWSIZE, filter = nil, &block)
89
+ rwsize = self::RWSIZE if rwsize.nil?
73
90
  self::open(filepath, "wb", rwsize) do |io|
74
- io.write(data) do |length|
75
- block.call(length)
91
+ io.write(data, filter) do |length|
76
92
  io.close()
93
+ block.call(length)
77
94
  end
78
95
  end
79
96
  end
@@ -82,7 +99,7 @@ module EM
82
99
 
83
100
  ##
84
101
  # Holds file object.
85
- # @return [::File]
102
+ # @return [IO]
86
103
  #
87
104
 
88
105
  attr_accessor :native
@@ -97,32 +114,64 @@ module EM
97
114
  @rw_len
98
115
 
99
116
  ##
100
- # Constructor.
117
+ # Holds mode of the object.
118
+ # @return [String]
101
119
  #
102
- # @param [String] filepath path to file
120
+
121
+ attr_reader :mode
122
+ @mode
123
+
124
+ ##
125
+ # Constructor. If IO object is given instead of filepath, uses
126
+ # it as native one and +mode+ argument is ignored.
127
+ #
128
+ # @param [String, IO] filepath path to file or IO object
103
129
  # @param [String] mode file access mode (see equivalent Ruby method)
104
130
  # @param [Integer] rwsize size of block operated during one tick
105
131
  #
106
132
 
107
- def initialize(filepath, mode = "r", rwsize = 65536)
108
- @native = ::File::open(filepath, mode)
133
+ def initialize(filepath, mode = "r", rwsize = self.class::RWSIZE)
134
+ @mode = mode
109
135
  @rw_len = rwsize
136
+
137
+ rwsize = self::RWSIZE if rwsize.nil?
138
+
139
+ # If filepath is directly IO, uses it
140
+ if filepath.kind_of? IO
141
+ @native = filepath
142
+ else
143
+ @native = ::File::open(filepath, mode)
144
+ end
145
+
110
146
  end
111
147
 
112
148
  ##
113
149
  # Reads data from file.
114
150
  #
151
+ # It will reopen the file if +EBADF: Bad file descriptor+ of
152
+ # +File+ class IO object will occur.
153
+ #
115
154
  # @overload read(length, &block)
116
155
  # Reads specified amount of data from file.
117
156
  # @param [Integer] length length for read from file
157
+ # @param [Proc] filter filter which for postprocessing each
158
+ # read chunk
118
159
  # @param [Proc] block callback for returning the result
119
160
  # @overload read(&block)
120
161
  # Reads whole content of file.
162
+ # @param [Proc] filter filter which for processing each block
121
163
  # @param [Proc] block callback for returning the result
122
164
  #
123
165
 
124
- def read(length = nil, &block)
166
+ def read(length = nil, filter = nil, &block)
125
167
  buffer = ""
168
+ pos = 0
169
+
170
+ # Arguments
171
+ if length.kind_of? Proc
172
+ filter = length
173
+ end
174
+
126
175
 
127
176
  worker = Proc::new do
128
177
 
@@ -137,7 +186,23 @@ module EM
137
186
  end
138
187
 
139
188
  # Reads
140
- buffer << @native.read(rlen)
189
+ begin
190
+ chunk = @native.read(rlen)
191
+ if not filter.nil?
192
+ chunk = filter.call(chunk)
193
+ end
194
+ buffer << chunk
195
+ rescue Errno::EBADF
196
+ if @native.kind_of? ::File
197
+ self.reopen!
198
+ @native.seek(pos)
199
+ redo
200
+ else
201
+ raise
202
+ end
203
+ end
204
+
205
+ pos = @native.pos
141
206
 
142
207
  # Returns or continues work
143
208
  if @native.eof? or (buffer.length == length)
@@ -153,22 +218,52 @@ module EM
153
218
  worker.call()
154
219
  end
155
220
 
221
+ ##
222
+ # Reopens the file with the original mode.
223
+ #
224
+
225
+ def reopen!
226
+ @native = ::File.open(@native.path, @mode)
227
+ end
228
+
156
229
  ##
157
230
  # Writes data to file.
158
231
  #
232
+ # It will reopen the file if +EBADF: Bad file descriptor+ of
233
+ # +File+ class IO object will occur.
234
+ #
159
235
  # @param [String] data data for write
236
+ # @param [Proc] filter filter which for preprocessing each
237
+ # written chunk
160
238
  # @param [Proc] block callback called when finish and for giving
161
239
  # back the length of written data
162
240
  #
163
241
 
164
- def write(data, &block)
242
+ def write(data, filter = nil, &block)
165
243
  written = 0
244
+ pos = 0
166
245
 
167
246
  worker = Proc::new do
168
247
 
169
248
  # Writes
170
- written += @native.write(data[written...(written + @rw_len)])
249
+ begin
250
+ chunk = data[written...(written + @rw_len)]
251
+ if not filter.nil?
252
+ chunk = filter.call(chunk)
253
+ end
254
+ written += @native.write(chunk)
255
+ rescue Errno::EBADF
256
+ if @native.kind_of? File
257
+ self.reopen!
258
+ @native.seek(pos)
259
+ redo
260
+ else
261
+ raise
262
+ end
263
+ end
171
264
 
265
+ pos = @native.pos
266
+
172
267
  # Returns or continues work
173
268
  if written >= data.bytesize
174
269
  if not block.nil?
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: em-files
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.1.1
5
+ version: 0.2.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - "Martin Koz\xC3\xA1k"
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-03-09 00:00:00 +01:00
13
+ date: 2011-03-19 00:00:00 +01:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -91,7 +91,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
91
91
  requirements:
92
92
  - - ">="
93
93
  - !ruby/object:Gem::Version
94
- hash: 50982926357626224
94
+ hash: -3958276784463008069
95
95
  segments:
96
96
  - 0
97
97
  version: "0"