io-stream 0.4.3 → 0.6.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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/lib/io/stream/generic.rb +67 -16
- data/lib/io/stream/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +2 -2
- metadata.gz.sig +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e7580fa6412067d9c5e341d3f81de6f9cd8134cc04fb1b2666bafc0a9685cc99
|
4
|
+
data.tar.gz: 76040e83616e06be4c7c0bbdfd89d019542b8d5eaa44c56af5e474acda870983
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9ac128c5e456067d97b9477ed715fc2d4b0698b3d01e2cb6884dfa2b28128b09a860cba4480f8b0a161c2d13c4ac956c00ddafee1b949f8f63f602e7ad277185
|
7
|
+
data.tar.gz: a381be911bb16224c57ad364dc8e4e85ce74616523360cbf62ab04d84747d3b47b133291c41dbac5e346cc01485dc85f2237f82c17a6612cf5404283d2be5c2e
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/lib/io/stream/generic.rb
CHANGED
@@ -18,6 +18,9 @@ module IO::Stream
|
|
18
18
|
# The maximum read size when appending to IO buffers. Defaults to 8MB.
|
19
19
|
MAXIMUM_READ_SIZE = ENV.fetch("IO_STREAM_MAXIMUM_READ_SIZE", BLOCK_SIZE * 128).to_i
|
20
20
|
|
21
|
+
class LimitError < StandardError
|
22
|
+
end
|
23
|
+
|
21
24
|
class Generic
|
22
25
|
def initialize(block_size: BLOCK_SIZE, maximum_read_size: MAXIMUM_READ_SIZE)
|
23
26
|
@eof = false
|
@@ -85,26 +88,37 @@ module IO::Stream
|
|
85
88
|
read_partial(size) or raise EOFError, "Encountered eof while reading data!"
|
86
89
|
end
|
87
90
|
|
88
|
-
|
89
|
-
# @param pattern [String] The pattern to match.
|
90
|
-
# @return [String] The contents of the stream up until the pattern, which is consumed but not returned.
|
91
|
-
def read_until(pattern, offset = 0, chomp: true)
|
91
|
+
private def index_of(pattern, offset, limit)
|
92
92
|
# We don't want to split on the pattern, so we subtract the size of the pattern.
|
93
93
|
split_offset = pattern.bytesize - 1
|
94
|
-
|
94
|
+
|
95
95
|
until index = @read_buffer.index(pattern, offset)
|
96
96
|
offset = @read_buffer.bytesize - split_offset
|
97
97
|
|
98
98
|
offset = 0 if offset < 0
|
99
99
|
|
100
|
-
return
|
100
|
+
return nil if limit and offset >= limit
|
101
|
+
return nil unless fill_read_buffer
|
101
102
|
end
|
102
103
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
104
|
+
return index
|
105
|
+
end
|
106
|
+
|
107
|
+
# Efficiently read data from the stream until encountering pattern.
|
108
|
+
# @parameter pattern [String] The pattern to match.
|
109
|
+
# @parameter offset [Integer] The offset to start searching from.
|
110
|
+
# @parameter limit [Integer] The maximum number of bytes to read, including the pattern (even if chomped).
|
111
|
+
# @returns [String | Nil] The contents of the stream up until the pattern, which is consumed but not returned.
|
112
|
+
def read_until(pattern, offset = 0, limit: nil, chomp: true)
|
113
|
+
if index = index_of(pattern, offset, limit)
|
114
|
+
return nil if limit and index >= limit
|
115
|
+
|
116
|
+
@read_buffer.freeze
|
117
|
+
matched = @read_buffer.byteslice(0, index+(chomp ? 0 : pattern.bytesize))
|
118
|
+
@read_buffer = @read_buffer.byteslice(index+pattern.bytesize, @read_buffer.bytesize)
|
119
|
+
|
120
|
+
return matched
|
121
|
+
end
|
108
122
|
end
|
109
123
|
|
110
124
|
def peek(size = nil)
|
@@ -124,8 +138,45 @@ module IO::Stream
|
|
124
138
|
return @read_buffer
|
125
139
|
end
|
126
140
|
|
127
|
-
def gets(separator = $/,
|
128
|
-
|
141
|
+
def gets(separator = $/, limit = nil, chomp: false)
|
142
|
+
# Compatibility with IO#gets:
|
143
|
+
if separator.is_a?(Integer)
|
144
|
+
limit = separator
|
145
|
+
separator = $/
|
146
|
+
end
|
147
|
+
|
148
|
+
# We don't want to split in the middle of the separator, so we subtract the size of the separator from the start of the search:
|
149
|
+
split_offset = separator.bytesize - 1
|
150
|
+
|
151
|
+
offset = 0
|
152
|
+
|
153
|
+
until index = @read_buffer.index(separator, offset)
|
154
|
+
offset = @read_buffer.bytesize - split_offset
|
155
|
+
offset = 0 if offset < 0
|
156
|
+
|
157
|
+
# If a limit was given, and the offset is beyond the limit, we should return up to the limit:
|
158
|
+
if limit and offset >= limit
|
159
|
+
# As we didn't find the separator, there is nothing to chomp either.
|
160
|
+
return consume_read_buffer(limit)
|
161
|
+
end
|
162
|
+
|
163
|
+
# If we can't read any more data, we should return what we have:
|
164
|
+
return consume_read_buffer unless fill_read_buffer
|
165
|
+
end
|
166
|
+
|
167
|
+
# If the index of the separator was beyond the limit:
|
168
|
+
if limit and index >= limit
|
169
|
+
# Return up to the limit:
|
170
|
+
return consume_read_buffer(limit)
|
171
|
+
end
|
172
|
+
|
173
|
+
# Freeze the read buffer, as this enables us to use byteslice without generating a hidden copy:
|
174
|
+
@read_buffer.freeze
|
175
|
+
|
176
|
+
line = @read_buffer.byteslice(0, index+(chomp ? 0 : separator.bytesize))
|
177
|
+
@read_buffer = @read_buffer.byteslice(index+separator.bytesize, @read_buffer.bytesize)
|
178
|
+
|
179
|
+
return line
|
129
180
|
end
|
130
181
|
|
131
182
|
private def drain(buffer)
|
@@ -148,8 +199,8 @@ module IO::Stream
|
|
148
199
|
|
149
200
|
# Writes `string` to the buffer. When the buffer is full or #sync is true the
|
150
201
|
# buffer is flushed to the underlying `io`.
|
151
|
-
# @
|
152
|
-
# @
|
202
|
+
# @parameter string [String] the string to write to the buffer.
|
203
|
+
# @returns [Integer] the number of bytes appended to the buffer.
|
153
204
|
def write(string, flush: false)
|
154
205
|
@writing.synchronize do
|
155
206
|
@write_buffer << string
|
@@ -292,7 +343,7 @@ module IO::Stream
|
|
292
343
|
end
|
293
344
|
|
294
345
|
# Consumes at most `size` bytes from the buffer.
|
295
|
-
# @
|
346
|
+
# @parameter size [Integer|nil] The amount of data to consume. If nil, consume entire buffer.
|
296
347
|
def consume_read_buffer(size = nil)
|
297
348
|
# If we are at eof, and the read buffer is empty, we can't consume anything.
|
298
349
|
return nil if @eof && @read_buffer.empty?
|
data/lib/io/stream/version.rb
CHANGED
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: io-stream
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Williams
|
@@ -37,7 +37,7 @@ cert_chain:
|
|
37
37
|
Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
|
38
38
|
voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
|
39
39
|
-----END CERTIFICATE-----
|
40
|
-
date: 2024-10-
|
40
|
+
date: 2024-10-15 00:00:00.000000000 Z
|
41
41
|
dependencies: []
|
42
42
|
description:
|
43
43
|
email:
|
metadata.gz.sig
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
�,)Ka�,x}Wjv_���G���ǁ���_C��S��C����k!�h��`Ȕ�A���l�+�����X���$��u�����G��ǭ��H���]��N�/�&b$�>C�}ۛfA]���⍣4m��Ⴑvȏ��R�z
|
2
|
+
$
|
3
|
+
l������G� ����
|
4
|
+
���x�|�&7�*V�Q�l�6Z#>y��\�x�E�
|
5
|
+
�6��}[Wsc��<������'�vP��O������:N)�Sn�!��2��:�gp�K.@7�\�y8yᵚO��\��'��8�^N��/�V�@��k���d0pݵ]��#�Vs%���I(9kX��eO76�
|