class MemoryIO::IO
Main class to use {MemoryIO}.
Attributes
stream[R]
Public Class Methods
new(stream)
click to toggle source
Instantiate an {IO} object.
@param [#pos, pos=, read
, write
] stream
The file-like object to be read/written. +file+ can be un-writable if you will not invoke any write-related method. If +stream.read(*)+ returns empty string or +nil+, it would be seen as reaching EOF.
# File lib/memory_io/io.rb, line 18 def initialize(stream) @stream = stream end
Public Instance Methods
read(num_elements, from: nil, as: nil, force_array: false)
click to toggle source
Read and convert result into custom type/structure.
@param [Integer] num_elements
Number of elements to be read. This parameter must be positive and larger than zero. This parameter may effect the return type, see documents of return value.
@param [Integer?] from
Invoke +stream.pos = from+ before starting to read. +nil+ for not changing current position of stream.
@param [nil, Symbol, Proc] as
Decide the type/structure when reading. See {MemoryIO::Types} for all supported types. A +Proc+ is allowed, which should accept +stream+ as the first argument. The return value of the proc would be the return objects of this method. If +nil+ is given, this method returns a string and has same behavior as +::IO#read+.
@param [Boolean] force_array
When +num_elements+ equals to 1, the read +Object+ would be returned. Pass +true+ to this parameter to force this method returning an array.
@return [String, Object, Array<Object>]
There're multiple possible return types, which depends on the value of parameter +num_elements+, +as+, and +force_array+. See examples for clear usage. The rule of return type is listed as following: * +as = nil+: A +String+ with length +num_elements+ is returned. * +as != nil+ and +num_elements = 1+ and +force_array = false+: An +Object+ is returned. The type of +Object+ depends on parameter +as+. * +as != nil+ and +num_elements = 1+ and +force_array = true+: An array with one element is returned. * +as != nil+ and +num_elements > 1+: An array with length +num_elements+ is returned. If EOF is occured, object(s) read will be returned.
@example
stream = StringIO.new('A' * 8 + 'B' * 8) io = MemoryIO::IO.new(stream) io.read(9) #=> "AAAAAAAAB" io.read(100) #=> "BBBBBBB" # read two unsigned 32-bit integers starts from posistion 4 io.read(2, from: 4, as: :u32) #=> [1094795585, 1111638594] # [0x41414141, 0x42424242] io.read(1, as: :u16) #=> 16962 # 0x4242 io.read(1, as: :u16, force_array: true) #=> [16962]
@example
stream = StringIO.new("\xef\xbe\xad\xde") io = MemoryIO::IO.new(stream) io.read(1, as: :u32) #=> 3735928559 io.rewind io.read(1, as: :s32) #=> -559038737
@example
stream = StringIO.new("123\x0045678\x00") io = MemoryIO::IO.new(stream) io.read(2, as: :c_str) #=> ["123", "45678"]
@example
# pass lambda to `as` stream = StringIO.new("\x03123\x044567") io = MemoryIO::IO.new(stream) io.read(2, as: lambda { |stream| stream.read(stream.read(1).ord) }) #=> ["123", "4567"]
@note
This method's arguments and return value are different with +::IO#read+. Check documents and examples.
@see Types
# File lib/memory_io/io.rb, line 103 def read(num_elements, from: nil, as: nil, force_array: false) stream.pos = from if from return stream.read(num_elements) if as.nil? conv = to_proc(as, :read) # TODO: handle eof ret = Array.new(num_elements) { conv.call(stream) } ret = ret.first if num_elements == 1 && !force_array ret end
rewind()
click to toggle source
Set stream
to the beginning. i.e. invoke +stream.pos = 0+.
@return [0]
# File lib/memory_io/io.rb, line 177 def rewind stream.pos = 0 end
write(objects, from: nil, as: nil)
click to toggle source
Write to stream.
@param [Object, Array<Object>] objects
Objects to be written.
@param [Integer] from
The position to start to write.
@param [nil, Symbol, Proc] as
Decide the method to process writing procedure. See {MemoryIO::Types} for all supported types. A +Proc+ is allowed, which should accept +stream+ and one object as arguments. If +objects+ is a descendant instance of {Types::Type} and +as+ is +nil, +objects.class+ will be used for +as+. Otherwise, when +as = nil+, this method will simply call +stream.write(objects)+.
@return [void]
@example
stream = StringIO.new io = MemoryIO::IO.new(stream) io.write('abcd') stream.string #=> "abcd" io.write([1, 2, 3, 4], from: 2, as: :u16) stream.string #=> "ab\x01\x00\x02\x00\x03\x00\x04\x00" io.write(['A', 'BB', 'CCC'], from: 0, as: :c_str) stream.string #=> "A\x00BB\x00CCC\x00\x00"
@example
stream = StringIO.new io = MemoryIO::IO.new(stream) io.write(%w[123 4567], as: ->(s, str) { s.write(str.size.chr + str) }) stream.string #=> "\x03123\x044567"
@example
stream = StringIO.new io = MemoryIO::IO.new(stream) cpp_string = CPP::String.new('A' * 4, 15, 16) # equivalent to io.write(cpp_string, as: :'cpp/string') io.write(cpp_string) stream.string #=> "\x10\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00AAAA\x00"
@see Types
# File lib/memory_io/io.rb, line 164 def write(objects, from: nil, as: nil) stream.pos = from if from as ||= objects.class if objects.class.ancestors.include?(MemoryIO::Types::Type) return stream.write(objects) if as.nil? conv = to_proc(as, :write) Array(objects).map { |o| conv.call(stream, o) } end
Private Instance Methods
to_proc(as, rw)
click to toggle source
@api private
# File lib/memory_io/io.rb, line 184 def to_proc(as, rw) ret = as.respond_to?(rw) ? as.method(rw) : as ret = ret.respond_to?(:call) ? ret : MemoryIO::Types.get_proc(ret, rw) raise ArgumentError, <<-EOERR.strip unless ret.respond_to?(:call) Invalid argument `as`: #{as.inspect}. It should be either a Proc or a supported type of MemoryIO::Types. EOERR ret end