939: def __diff_direction(src, patchset, limit = nil)
940: count = left = left_miss = right = right_miss = 0
941: string = src.kind_of?(String)
942:
943: patchset.each do |change|
944: count += 1
945:
946: case change
947: when Diff::LCS::Change
948:
949:
950:
951: element = string ? src[change.position, 1] : src[change.position]
952:
953: case change.action
954: when '-'
955: if element == change.element
956: left += 1
957: else
958: left_miss += 1
959: end
960: when '+'
961: if element == change.element
962: right += 1
963: else
964: right_miss += 1
965: end
966: when '='
967: if element != change.element
968: left_miss += 1
969: right_miss += 1
970: end
971: end
972: when Diff::LCS::ContextChange
973: case change.action
974: when '-'
975: element = string ? src[change.old_position, 1] : src[change.old_position]
976: if element == change.old_element
977: left += 1
978: else
979: left_miss += 1
980: end
981: when '+'
982: element = string ? src[change.new_position, 1] : src[change.new_position]
983: if element == change.new_element
984: right += 1
985: else
986: right_miss += 1
987: end
988: when '='
989: le = string ? src[change.old_position, 1] : src[change.old_position]
990: re = string ? src[change.new_position, 1] : src[change.new_position]
991:
992: left_miss += 1 if le != change.old_element
993: right_miss += 1 if re != change.new_element
994: when '!'
995: element = string ? src[change.old_position, 1] : src[change.old_position]
996: if element == change.old_element
997: left += 1
998: else
999: element = string ? src[change.new_position, 1] : src[change.new_position]
1000: if element == change.new_element
1001: right += 1
1002: else
1003: left_miss += 1
1004: right_miss += 1
1005: end
1006: end
1007: end
1008: end
1009:
1010: break if not limit.nil? and count > limit
1011: end
1012:
1013: no_left = (left == 0) and (left_miss >= 0)
1014: no_right = (right == 0) and (right_miss >= 0)
1015:
1016: case [no_left, no_right]
1017: when [false, true]
1018: return :patch
1019: when [true, false]
1020: return :unpatch
1021: else
1022: raise "The provided patchset does not appear to apply to the provided value as either source or destination value."
1023: end
1024: end