ioblockreader 1.0.1.20130611 → 1.0.2.20130613

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/AUTHORS CHANGED
@@ -2,3 +2,4 @@
2
2
 
3
3
  * 1.0.0.20130611
4
4
  * 1.0.1.20130611
5
+ * 1.0.2.20130613
data/ChangeLog CHANGED
@@ -1,5 +1,10 @@
1
1
  = IOBlockReader Release History
2
2
 
3
+ == 1.0.2.20130613 (Beta)
4
+
5
+ * Added each_block interface
6
+ * Make internal string use encoding of the IO for Ruby >= 1.9
7
+
3
8
  == 1.0.1.20130611 (Beta)
4
9
 
5
10
  * Adapted test suite for Ruby 1.8
data/README.md CHANGED
@@ -34,6 +34,8 @@ end
34
34
 
35
35
  ### IOBlockReader.init(io, options = {})
36
36
 
37
+ Get an IOBlockReader instance on an IO.
38
+
37
39
  Parameters:
38
40
  * **io** ( _IO_ ): The IO object used to give the String interface
39
41
  * **options** (<em>map< Symbol, Object ></em>): Additional options:
@@ -50,6 +52,8 @@ content = IOBlockReader.init(file, :block_size => 32768, :blocks_in_memory => 5)
50
52
 
51
53
  ### IOBlockReader#\[\](range)
52
54
 
55
+ Access a part of the data in the IO as a String.
56
+
53
57
  Parameters:
54
58
  * **range** ( _Fixnum_ or _Range_ ): Range to extract
55
59
 
@@ -64,6 +68,8 @@ substring = content[10..20]
64
68
 
65
69
  ### IOBlockReader#index(token, offset = 0, max_size_regexp = 32)
66
70
 
71
+ Search for a token or a list of tokens.
72
+
67
73
  Parameters:
68
74
  * **token** ( _String_ , _Regexp_ or <em>list< Object ></em>): Token to be found. Can be a list of tokens.
69
75
  * **offset** ( _Fixnum_ ): Offset starting the search [optional = 0]
@@ -94,6 +100,30 @@ i, token_index = content.index( [ 'search string', 'another string' ] )
94
100
  i, token_index = content.index( [ 'search string', /another f.....g string/ ], 20, 22)
95
101
  ```
96
102
 
103
+ ### IOBlockReader#each_block(range = 0)
104
+
105
+ Iterate over blocks in the data.
106
+
107
+ Parameters:
108
+ * **range** ( _Range_ or _Fixnum_ ): The boundaries of the iteration, or the starting index [default = 0]
109
+ * _Block_ : Code called for each block encountered
110
+ * Parameters:
111
+ * **data** ( _String_ ): The data
112
+
113
+ Example:
114
+ ```
115
+ # Iterate all over the IO
116
+ content.each_block do |data|
117
+ puts "Got a block of #{data.size} bytes"
118
+ end
119
+
120
+ # Iterate on just a part
121
+ content.each_block(10..50) do |data|
122
+ puts "Got a block of #{data.size} bytes"
123
+ end
124
+
125
+ ```
126
+
97
127
  ## Contact
98
128
 
99
129
  Want to contribute? Have any questions? [Contact Muriel!](muriel@x-aeon.com)
data/ReleaseInfo CHANGED
@@ -2,7 +2,7 @@
2
2
  # This file has been generated by RubyPackager during a delivery.
3
3
  # More info about RubyPackager: http://rubypackager.sourceforge.net
4
4
  {
5
- :version => '1.0.1.20130611',
5
+ :version => '1.0.2.20130613',
6
6
  :tags => [ 'Beta' ],
7
7
  :dev_status => 'Beta'
8
8
  }
@@ -19,26 +19,30 @@ module IOBlockReader
19
19
  attr_reader :data
20
20
 
21
21
  # Constructor
22
- def initialize
22
+ #
23
+ # Parameters::
24
+ # * *io* (_IO_): IO to read from
25
+ def initialize(io)
26
+ @io = io
23
27
  @offset = nil
24
28
  @last_access_time = nil
25
29
  @data = ''
30
+ @data.force_encoding(@io.external_encoding) if (@data.respond_to?(:force_encoding))
26
31
  end
27
32
 
28
33
  # Fill the data block for a given IO
29
34
  #
30
35
  # Parameters::
31
- # * *io* (_IO_): IO to read from
32
36
  # * *offset* (_Fixnum_): Offset of this block in the IO
33
37
  # * *size* (_Fixnum_): Size of the block to be read
34
- def fill(io, offset, size)
38
+ def fill(offset, size)
35
39
  @offset = offset
36
40
  @last_access_time = @@access_time_sequence
37
41
  @@access_time_sequence += 1
38
42
  #puts "[IOBlockReader] - Read #{size} @#{@offset}"
39
- io.seek(@offset)
40
- io.read(size, @data)
41
- @last_block = io.eof?
43
+ @io.seek(@offset)
44
+ @io.read(size, @data)
45
+ @last_block = @io.eof?
42
46
  end
43
47
 
44
48
  # Is this block the last of its IO stream?
@@ -199,6 +199,77 @@ module IOBlockReader
199
199
  end
200
200
  end
201
201
 
202
+ # Iterate over blocks in the data.
203
+ # ! Do not use negative integers in the range.
204
+ #
205
+ # Parameters::
206
+ # * *range* (_Range_ or _Fixnum_): The boundaries of the iteration, or the starting index [default = 0]
207
+ # * _Block_: Code called for each block encountered
208
+ # * Parameters::
209
+ # * *data* (_String_): The data
210
+ def each_block(range = 0)
211
+ #puts "[IOBlockReader] - each_block(#{range})"
212
+ # Parse parameters
213
+ begin_offset = range
214
+ end_offset = nil
215
+ if (range.is_a?(Range))
216
+ begin_offset = range.first
217
+ end_offset = range.last
218
+ end
219
+
220
+ current_block_index, begin_offset_in_first_block = begin_offset.divmod(@block_size)
221
+ end_offset_block_index, end_offset_in_last_block = ((end_offset == nil) ? [nil, nil] : end_offset.divmod(@block_size))
222
+ # Make sure first block is loaded
223
+ if ((current_block = @blocks[current_block_index]) == nil)
224
+ read_needed_blocks([current_block_index], current_block_index, current_block_index)
225
+ current_block = @blocks[current_block_index]
226
+ else
227
+ current_block.touch
228
+ end
229
+ if (current_block_index == end_offset_block_index)
230
+ # We have a Range in the same block
231
+ if ((begin_offset_in_first_block == 0) and
232
+ (end_offset_in_last_block == current_block.data.size-1))
233
+ yield(current_block.data)
234
+ else
235
+ yield(current_block.data[begin_offset_in_first_block..end_offset_in_last_block])
236
+ end
237
+ else
238
+ # We need to loop, but consider first block differently as it might be partially given
239
+ if (begin_offset_in_first_block == 0)
240
+ yield(current_block.data)
241
+ else
242
+ yield(current_block.data[begin_offset_in_first_block..-1])
243
+ end
244
+ if (!current_block.last_block?)
245
+ # Now loop on all subsequent blocks unless we get to the last one
246
+ finished = false
247
+ while (!finished)
248
+ # Read next block
249
+ current_block_index += 1
250
+ if ((current_block = @blocks[current_block_index]) == nil)
251
+ read_needed_blocks([current_block_index], current_block_index, current_block_index)
252
+ current_block = @blocks[current_block_index]
253
+ else
254
+ current_block.touch
255
+ end
256
+ if (end_offset_block_index == current_block_index)
257
+ # We arrived on the last block of the Range
258
+ if (end_offset_in_last_block == current_block.data.size-1)
259
+ yield(current_block.data)
260
+ else
261
+ yield(current_block.data[0..end_offset_in_last_block])
262
+ end
263
+ finished = true
264
+ else
265
+ yield(current_block.data)
266
+ finished = current_block.last_block?
267
+ end
268
+ end
269
+ end
270
+ end
271
+ end
272
+
202
273
  private
203
274
 
204
275
  # Set the new cache block
@@ -246,8 +317,8 @@ module IOBlockReader
246
317
  indexes_needing_loading.each do |block_index|
247
318
  # Have to load this block
248
319
  block_to_fill = removed_blocks.pop
249
- block_to_fill = DataBlock.new if (block_to_fill == nil)
250
- block_to_fill.fill(@io, block_index * @block_size, @block_size)
320
+ block_to_fill = DataBlock.new(@io) if (block_to_fill == nil)
321
+ block_to_fill.fill(block_index * @block_size, @block_size)
251
322
  @blocks[block_index] = block_to_fill
252
323
  end
253
324
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ioblockreader
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1.20130611
4
+ version: 1.0.2.20130613
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-06-11 00:00:00.000000000 Z
12
+ date: 2013-06-13 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: Ruby library giving block-buffered and cached read over IO objects with
15
15
  a String-like interface. Ideal to parse big files as Strings, limiting memory consumption.