Module: External::Utils

Defined in:
lib/external/utils.rb,
lib/external/patches/windows_utils.rb

Class Method Summary collapse

Class Method Details

.file_length(io) ⇒ Object

Modfied to properly determine file lengths on Windows. Uses code from ‘win32/file/stat’ (rubyforge.org/projects/win32utils/)



10
11
12
# File 'lib/external/patches/windows_utils.rb', line 10

def file_length(io)
  io_length(io)
end

.file_mode(io) ⇒ Object



113
114
115
# File 'lib/external/utils.rb', line 113

def file_mode(io)
  io_mode(io)
end

.io_length(io) ⇒ Object

Returns the length of the input IO



108
109
110
111
# File 'lib/external/utils.rb', line 108

def io_length(io)
  io.fsync
  io.stat.size
end

.io_mode(io) ⇒ Object

Returns an array of bools determining if the input Io is readable and writable.



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/external/utils.rb', line 83

def io_mode(io)
  begin
    dup = io.dup
    
    # determine readable/writable by sending close methods
    # to the duplicated Io.  If the io cannot  be closed for 
    # read/write then it will raise an error, indicating that 
    # it was not open in the given mode.   
    [:close_read, :close_write].collect do |method|
      begin
        dup.send(method)
        true
      rescue(IOError)
        false
      end
    end
  ensure
    # Be sure that the dup is fully closed before proceeding!  
    # (Otherwise Tempfiles will not be properly disposed of
    # ... at least on Windows, perhaps on others)
    dup.close if dup && !dup.closed?
  end
end

.length(io) ⇒ Object

Determines the length of the input io using the _length method for the input io class. Non-External::Io inputs are extended in this process.

The _length method takes the input io, and should return the current length of the input io (ie a flush operation may be required).

See try_handle for more details.



72
73
74
75
76
77
78
79
# File 'lib/external/utils.rb', line 72

def length(io)
  case io
  when Io then try_handle(io, "length")
  else
    io.extend Io
    io.length
  end
end

.mode(io) ⇒ Object

Determines the generic mode of the input io using the _mode method for the input io class. By default Io provides _mode methods for File, Tempfile, and StringIo. The return string is determined as follows:

readable & writable

r+

readable

r

writable

w

The _mode method takes the input io and should return an array specifying whether or not io is readable and writable (ie [readable, writable]).

See try_handle for more details.



50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/external/utils.rb', line 50

def mode(io) 
  readable, writable = try_handle(io, "mode")

  case
  when readable && writable then "r+"
  when readable then "r"
  when writable then "w"
  else
    # occurs for r+ mode, for some reason
    "r+"
  end
end

.stringio_length(io) ⇒ Object

Returns the length of the input StringIo

s = StringIo.new("abcde", "r+")
External::Io.length(s)  # => 5


147
148
149
# File 'lib/external/utils.rb', line 147

def stringio_length(io)
  io.string.length
end

.stringio_mode(io) ⇒ Object

Returns an array of bools determining if the input StringIo is readable and writable.

s = StringIo.new("abcde", "r+")
External::Io.stringio_mode(s)  # => [true, true]


138
139
140
# File 'lib/external/utils.rb', line 138

def stringio_mode(io)
  [!io.closed_read?, !io.closed_write?]
end

.tempfile_length(io) ⇒ Object

Returns the length of the input Tempfile



128
129
130
# File 'lib/external/utils.rb', line 128

def tempfile_length(io)
  file_length(io)
end

.tempfile_mode(io) ⇒ Object

Returns an array of bools determining if the input Tempfile is readable and writable.



123
124
125
# File 'lib/external/utils.rb', line 123

def tempfile_mode(io)
  file_mode(io.instance_variable_get(:@tmpfile))
end

.try_handle(io, method) ⇒ Object

try_handle is a forwarding method allowing External::IO to handle non-File, non-Tempfile IO objects. try_handle infers a method name based on the class of the input and trys to forward the input io to that method within External::IO. For instance:

  • the _mode method for StringIO is ‘stringio_mode’

  • the _length method for StringIO is ‘stringio_length’

Nested classes have ‘::’ replaced by ‘_’. Thus to add support for Some::Unknown::IO, extend External::IO as below:

module External::IO
  def some_unknown_io_mode(io)
  ...
  end

  def some_unknown_io_length(io)
  ...
  end
end

See stringio_mode and stringio_length for more details.



27
28
29
30
31
32
33
34
# File 'lib/external/utils.rb', line 27

def try_handle(io, method)
  method_name = io.class.to_s.downcase.gsub(/::/, "_") + "_#{method}"
  if Utils.respond_to?(method_name)
    Utils.send(method_name, io)
  else
    raise "cannot determine #{method} for '%s'" % io.class
  end
end