Class: Diff::GDiff
- Inherits:
-
Object
- Object
- Diff::GDiff
- Defined in:
- lib/gdiff.rb,
lib/gdiff.rb
Overview
Class encapsulating the gdiff protocoll
Defined Under Namespace
Modules: Operations Classes: EGdiffError, ENoGdiffStream, EPrematureEndOfStream
Class Method Summary collapse
-
.unpack(string) ⇒ Object
Unpack a binary representation of a diff.
Instance Method Summary collapse
-
#apply_to(a) ⇒ Object
Apply this patch to a string, yielding another string.
-
#initialize(a = nil, b = nil, threshhold = 5) ⇒ GDiff
constructor
Create a new gdiff patch from string a to string b.
-
#pack ⇒ Object
Return a binary representation in GDiff format.
-
#to_s ⇒ Object
Return a readable string representation.
Constructor Details
#initialize(a = nil, b = nil, threshhold = 5) ⇒ GDiff
Create a new gdiff patch from string a to string b. Threshhold needs to be estimated more exactly to yield the best possible compression.
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 |
# File 'lib/gdiff.rb', line 175 def initialize(a = nil, b = nil, threshhold = 5) if (!a and !b) or b.empty? @operations = [] elsif a.empty? @operations = [Operations::Data.new(b)] else # Lifted the suffix array and this algorithm from zed shaws fastcst project # http://www.zedshaw.com/projects/fastcst/rdoc/index.html # # It is licenced under the gpl, so now my code is also licensed under the gpl sary = SuffixArray.new(a) @operations = [] start = 0 while start < b.length non_len, match_start, match_len = sary.longest_nonmatch b, start, threshhold @operations << Operations::Data.new(b[start, non_len]) if non_len > 0 @operations << Operations::Copy.new(match_start, match_len) if match_len > 0 start += non_len + match_len end @operations << Operations::EOS end end |
Class Method Details
.unpack(string) ⇒ Object
Unpack a binary representation of a diff.
TODO: use stream operations to allow reading the diff step by step from an io.
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
# File 'lib/gdiff.rb', line 209 def self.unpack(string) result = self.new result.instance_eval do raise ENoGdiffStream, "No gdiff stream." if string[0,5].unpack("C5") != [0xd1, 0xff, 0xd1, 0xff, 4] position = 5 while string[position] != 0 position, operation = (Operations::Data.unpack_if_match(string, position) or Operations::Copy.unpack_if_match(string, position)) @operations << operation raise EPrematureEndOfStream, "Premature end of gdiff stream" if position >= string.length end @operations << Operations::EOS end result end |
Instance Method Details
#apply_to(a) ⇒ Object
Apply this patch to a string, yielding another string.
TODO: Implement a stream version that writes successively to a stream and saves memory.
229 230 231 232 233 234 235 236 237 238 239 240 |
# File 'lib/gdiff.rb', line 229 def apply_to(a) result = "" @operations.each do | operation | case operation when Operations::Copy result << a[operation.position, operation.length] when Operations::Data result << operation.data end end result end |
#pack ⇒ Object
Return a binary representation in GDiff format
248 249 250 |
# File 'lib/gdiff.rb', line 248 def pack [0xd1, 0xff, 0xd1, 0xff, 4].pack("C5") << @operations.map { | operation | operation.pack }.join end |
#to_s ⇒ Object
Return a readable string representation
243 244 245 |
# File 'lib/gdiff.rb', line 243 def to_s @operations.map { | operation | operation.to_s } end |