Class: RubyTorrent::Covering
- Inherits:
-
Object
- Object
- RubyTorrent::Covering
- Defined in:
- lib/rubytorrent/package.rb
Overview
a Covering is a set of non-overlapping ranges within a given start point and endpoint.
Instance Attribute Summary collapse
-
#domain ⇒ Object
Returns the value of attribute domain.
-
#ranges ⇒ Object
Returns the value of attribute ranges.
Instance Method Summary collapse
- #==(o) ⇒ Object
- #complete! ⇒ Object
- #complete? ⇒ Boolean
- #empty! ⇒ Object
- #empty? ⇒ Boolean
-
#fill(r) ⇒ Object
given a covering of size N and a new range ‘r’, returns a covering of size 0 < s <= N + 1 that also covers the range ‘r’.
-
#first_gap(domain = @domain) ⇒ Object
given an array of non-overlapping ranges sorted by start point, and a range ‘domain’, returns the first range from ‘domain’ not covered by any range in the array.
-
#initialize(domain, ranges = []) ⇒ Covering
constructor
‘domain’ should be an AwesomeRange determining the start and end point.
-
#poke(r) ⇒ Object
given a covering of size N and a new range ‘r’, returns a covering of size 0 <= s <= N + 1 that doesn’t cover the range given by ‘r’.
Constructor Details
#initialize(domain, ranges = []) ⇒ Covering
‘domain’ should be an AwesomeRange determining the start and end point. ‘ranges’ should be an array of non-overlapping AwesomeRanges sorted by start point.
108 109 110 111 |
# File 'lib/rubytorrent/package.rb', line 108 def initialize(domain, ranges=[]) @domain = domain @ranges = ranges end |
Instance Attribute Details
#domain ⇒ Object
Returns the value of attribute domain.
103 104 105 |
# File 'lib/rubytorrent/package.rb', line 103 def domain @domain end |
#ranges ⇒ Object
Returns the value of attribute ranges.
103 104 105 |
# File 'lib/rubytorrent/package.rb', line 103 def ranges @ranges end |
Instance Method Details
#==(o) ⇒ Object
194 |
# File 'lib/rubytorrent/package.rb', line 194 def ==(o); o.domain == self.domain && o.ranges == self.ranges; end |
#complete! ⇒ Object
113 |
# File 'lib/rubytorrent/package.rb', line 113 def complete!; @ranges = [@domain]; self; end |
#complete? ⇒ Boolean
114 |
# File 'lib/rubytorrent/package.rb', line 114 def complete?; @ranges == [@domain]; end |
#empty! ⇒ Object
115 |
# File 'lib/rubytorrent/package.rb', line 115 def empty!; @ranges = []; self; end |
#empty? ⇒ Boolean
116 |
# File 'lib/rubytorrent/package.rb', line 116 def empty?; @ranges == []; end |
#fill(r) ⇒ Object
given a covering of size N and a new range ‘r’, returns a covering of size 0 < s <= N + 1 that also covers the range ‘r’.
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/rubytorrent/package.rb', line 134 def fill(r) raise ArgumentError, "#{r} outside of domain #@domain" unless @domain.rss? r Covering.new(@domain, @ranges.inject([]) do |set, x| ## r contains the result of the continuing merge. if r is nil, ## then we've already added it, so we just copy x. if r.nil? then set + [x] else ## otoh, if r is there, we try and merge in the current ## element. if r.rcont? x ## if we can merge, keep the union in r and don't add ## anything r = r.runion x set ## if we can't merge it, we'll see if it's time to add it. we ## know that r and x don't overlap because r.mergable?(x) was ## false, so we can simply compare the start points to see ## whether it should come before x. elsif r.first < x.first s = set + [r, x] # add both r = nil s else set + [x] ## no merging or adding, so we just copy x. end end ## if 'r' still hasn't been added, it should be the last element, ## we add it here. end.push(r).compact) end |
#first_gap(domain = @domain) ⇒ Object
given an array of non-overlapping ranges sorted by start point, and a range ‘domain’, returns the first range from ‘domain’ not covered by any range in the array.
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
# File 'lib/rubytorrent/package.rb', line 166 def first_gap(domain=@domain) start = domain.first endd = nil excl = nil @ranges.each do |r| next if r.last < start if r.first > start # found a gap if r.first < domain.last return AwesomeRange.new(start, r.first, false) else # r.first >= domain.last, so use domain's exclusion return AwesomeRange.new(start, domain.last, domain.exclude_end?) end else # r.first <= start start = r.last unless r.last < start break if start > domain.last end end if (start >= domain.last) ## entire domain was covered nil else ## tail end of the domain uncovered AwesomeRange.new(start, domain.last, domain.exclude_end?) end end |
#poke(r) ⇒ Object
given a covering of size N and a new range ‘r’, returns a covering of size 0 <= s <= N + 1 that doesn’t cover the range given by ‘r’.
121 122 123 124 125 126 127 128 129 130 |
# File 'lib/rubytorrent/package.rb', line 121 def poke(r) raise ArgumentError, "#{r} outside of domain #@domain" unless @domain.rss? r Covering.new(@domain, @ranges.inject([]) do |set, x| if x.rint(r) != nil set + x.rdiff(r) else set + [x] end end) end |