Commit 34a349b2 by Janko Marohnić Committed by GitHub

Merge pull request #41 from janko-m/io-like-objects

Support IO-like objects efficiently
parents 7cd73b35 9ebbf0d9
...@@ -109,28 +109,27 @@ class MimeMagic ...@@ -109,28 +109,27 @@ class MimeMagic
end end
def self.magic_match(io, method) def self.magic_match(io, method)
if io.respond_to?(:seek) && io.respond_to?(:read) return magic_match(StringIO.new(io.to_s), method) unless io.respond_to?(:read)
io.binmode
io.binmode if io.respond_to?(:binmode)
io.set_encoding(Encoding::BINARY) if io.respond_to?(:set_encoding) io.set_encoding(Encoding::BINARY) if io.respond_to?(:set_encoding)
buffer = "".force_encoding(Encoding::BINARY) buffer = "".force_encoding(Encoding::BINARY)
MAGIC.send(method) { |type, matches| magic_match_io(io, matches, buffer) } MAGIC.send(method) { |type, matches| magic_match_io(io, matches, buffer) }
else
str = io.respond_to?(:read) ? io.read : io.to_s
magic_match(StringIO.new(str), method)
end
end end
def self.magic_match_io(io, matches, buffer) def self.magic_match_io(io, matches, buffer)
matches.any? do |offset, value, children| matches.any? do |offset, value, children|
match = match =
if Range === offset if Range === offset
io.seek(offset.begin) io.read(offset.begin, buffer)
x = io.read(offset.end - offset.begin + value.bytesize, buffer) x = io.read(offset.end - offset.begin + value.bytesize, buffer)
x && x.include?(value) x && x.include?(value)
else else
io.seek(offset) io.read(offset, buffer)
io.read(value.bytesize, buffer) == value io.read(value.bytesize, buffer) == value
end end
io.rewind
match && (!children || magic_match_io(io, children, buffer)) match && (!children || magic_match_io(io, children, buffer))
end end
end end
......
require 'bacon' require 'bacon'
require 'mimemagic' require 'mimemagic'
require 'stringio' require 'stringio'
require 'forwardable'
describe 'MimeMagic' do describe 'MimeMagic' do
it 'should have type, mediatype and subtype' do it 'should have type, mediatype and subtype' do
...@@ -116,12 +117,15 @@ describe 'MimeMagic' do ...@@ -116,12 +117,15 @@ describe 'MimeMagic' do
it 'should handle different file objects' do it 'should handle different file objects' do
MimeMagic.add('application/mimemagic-test', magic: [[0, 'MAGICTEST']]) MimeMagic.add('application/mimemagic-test', magic: [[0, 'MAGICTEST']])
class ReadableObj class IOObject
def read def initialize
'MAGICTEST' @io = StringIO.new('MAGICTEST')
end end
extend Forwardable
delegate [:read, :size, :rewind, :eof?, :close] => :@io
end end
MimeMagic.by_magic(ReadableObj.new).should.equal 'application/mimemagic-test' MimeMagic.by_magic(IOObject.new).should.equal 'application/mimemagic-test'
class StringableObject class StringableObject
def to_s def to_s
'MAGICTEST' 'MAGICTEST'
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment