Module: External::Io

Includes:
Chunkable
Defined in:
lib/external/io.rb

Overview

Adds functionality to an IO required by External.

IO adds/overrides the length accessor for getting the size of the IO contents.

Note that length is not automatically adjusted by write, for performance reasons. length must be managed manually, or reset after writes using reset_length.

Constant Summary collapse

PATCHES =
[]

Instance Attribute Summary

Attributes included from Chunkable

#default_blksize, #length

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Chunkable

#chunk, #default_span, range_begin_and_end, #reverse_chunk, split_range, split_span

Class Method Details

.extended(base) ⇒ Object

Add platform-specific patches case RUBY_PLATFORM when ‘java’ end



32
33
34
35
36
37
# File 'lib/external/io.rb', line 32

def self.extended(base)
  PATCHES.each {|patch| base.extend patch }
  base.reset_length
  base.default_blksize = 1024
  base.binmode
end

Instance Method Details

#<=>(another) ⇒ Object

Alias for sort_compare.



159
160
161
# File 'lib/external/io.rb', line 159

def <=>(another)
  sort_compare(another)
end

#concat(src, range = 0..src.length) ⇒ Object



84
85
86
# File 'lib/external/io.rb', line 84

def concat(src, range=0..src.length)
  insert(src, range, length)
end

#copy(mode = "r", range = 0..length) ⇒ Object

– it appears that as long as the io opening t.path closes, the tempfile will be deleted at the exit of the ruby instance… otherwise it WILL NOT BE DELETED Make note of this in the documentation to be sure to close files if you start inserting because it may make tempfiles ++



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/external/io.rb', line 95

def copy(mode="r", range=0..length)
  self.flush
  
  temp = Tempfile.new("copy")
  temp.extend Io
  temp.insert(self, range)
  temp.close

  cp = File.open(temp.path, mode)
  cp.extend Io

  if block_given?
    begin
      yield(cp)
    ensure
      cp.close unless cp.closed?
      FileUtils.rm(cp.path) if File.exists?(cp.path)
    end
  else
    cp
  end
end

#insert(src, range = 0..src.length, pos = nil) ⇒ Object



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/external/io.rb', line 66

def insert(src, range=0..src.length, pos=nil)
  self.pos = pos unless pos == nil
  
  start_pos = self.pos
  length_written = 0

  src.flush
  src.pos = range.begin 
  src.chunk(range) do |offset, length|
    length_written += write(src.read(length))
  end

  end_pos = start_pos + length_written
  self.length = end_pos if end_pos > self.length
  length_written
end

#quick_compare(another) ⇒ Object

Quick comparision with another IO. Returns true if another == self, or if both are file-type IOs and their paths are equal.



121
122
123
# File 'lib/external/io.rb', line 121

def quick_compare(another)
  self == another || (self.kind_of?(File) && another.kind_of?(File) && self.path == another.path)
end

#reset_lengthObject

Resets length to the length returned by Utils.length



40
41
42
# File 'lib/external/io.rb', line 40

def reset_length
  self.length = Utils.length(self)
end

#scan(range_or_span = default_span, blksize = default_blksize, carryover_limit = default_blksize) ⇒ Object



52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/external/io.rb', line 52

def scan(range_or_span=default_span, blksize=default_blksize, carryover_limit=default_blksize)
  carryover = 0
  chunk(range_or_span, blksize) do |offset, length|
    raise "carryover exceeds limit: #{carryover} (#{carryover_limit})" if carryover > carryover_limit
    
    scan_begin = offset - carryover
    self.pos = scan_begin
    string = self.read(length + carryover)
    carryover = yield(scan_begin, string)
  end
  carryover
end

#sort_compare(another, blksize = default_blksize) ⇒ Object

Sort compare (ie <=>) with another IO, behaving like a comparison between the full string contents of self and another. This obviously can be a long operation if it requires the full read of two large IO objects.



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/external/io.rb', line 129

def sort_compare(another, blksize=default_blksize)
  # equal in comparison if the ios are equal
  return 0 if quick_compare(another)
  
  self.flush
  self.reset_length
  
  another.flush
  another.reset_length
  
  if another.length > self.length
    return -1
  elsif self.length < another.length
    return 1
  else
    self.pos = 0
    another.pos = 0

    sa = sb = nil
    while sa == sb
      sa = self.read(blksize)
      sb = another.read(blksize)
      break if sa.nil? || sb.nil?
    end

    sa.to_s <=> sb.to_s
  end
end

#truncate(n) ⇒ Object

Modified truncate that adjusts length



45
46
47
48
49
# File 'lib/external/io.rb', line 45

def truncate(n)
  super
  self.pos = n if self.pos > n
  self.length = n
end