1 11 package org.eclipse.compare.internal.patch; 12 13 import java.util.List ; 14 15 import org.eclipse.compare.patch.PatchConfiguration; 16 import org.eclipse.core.runtime.Assert; 17 18 21 public class Hunk { 22 23 public static final int ADDED = 0x1; 24 public static final int DELETED = 0x2; 25 public static final int CHANGED = 0x4; 26 public static final int UNKNOWN = 0x8; 27 28 private FileDiff fParent; 29 private int fOldStart, fOldLength; 30 private int fNewStart, fNewLength; 31 private String [] fLines; 32 private int hunkType; 33 34 public Hunk(FileDiff parent, Hunk toCopy) { 35 fParent = parent; 36 if (fParent != null) { 37 fParent.add(this); 38 } 39 40 fOldStart = toCopy.fOldStart; 41 fOldLength = toCopy.fOldLength; 42 fNewStart = toCopy.fNewStart; 43 fNewLength = toCopy.fOldLength; 44 fLines = toCopy.fLines; 45 hunkType = toCopy.hunkType; 46 } 47 48 public Hunk(FileDiff parent, int[] oldRange, int[] newRange, List lines, boolean encounteredPlus, boolean encounteredMinus, boolean encounteredSpace) { 49 50 fParent= parent; 51 if (fParent != null) 52 fParent.add(this); 53 54 if (oldRange[0] > 0) 55 fOldStart= oldRange[0]-1; else 57 fOldStart= 0; 58 fOldLength= oldRange[1]; 59 if (newRange[0] > 0) 60 fNewStart= newRange[0]-1; else 62 fNewStart= 0; 63 fNewLength= newRange[1]; 64 65 fLines= (String []) lines.toArray(new String [lines.size()]); 66 67 if (encounteredSpace && (encounteredPlus || encounteredMinus)){ 68 hunkType = CHANGED; 69 } else if (encounteredPlus && !encounteredMinus && !encounteredSpace){ 70 hunkType = ADDED; 71 } else if (!encounteredPlus && encounteredMinus && !encounteredSpace) { 72 hunkType = DELETED; 73 } else { 74 hunkType = UNKNOWN; 75 } 76 } 77 78 90 String getContent() { 91 StringBuffer sb= new StringBuffer (); 92 for (int i= 0; i < fLines.length; i++) { 93 String line= fLines[i]; 94 sb.append(line.substring(0, Patcher.length(line))); 95 sb.append('\n'); 96 } 97 return sb.toString(); 98 } 99 100 104 String getDescription() { 105 StringBuffer sb= new StringBuffer (); 106 sb.append(Integer.toString(fOldStart)); 107 sb.append(','); 108 sb.append(Integer.toString(fOldLength)); 109 sb.append(" -> "); sb.append(Integer.toString(fNewStart)); 111 sb.append(','); 112 sb.append(Integer.toString(fNewLength)); 113 return sb.toString(); 114 } 115 116 String getRejectedDescription() { 117 StringBuffer sb= new StringBuffer (); 118 sb.append("@@ -"); sb.append(Integer.toString(fOldStart)); 120 sb.append(','); 121 sb.append(Integer.toString(fOldLength)); 122 sb.append(" +"); sb.append(Integer.toString(fNewStart)); 124 sb.append(','); 125 sb.append(Integer.toString(fNewLength)); 126 sb.append(" @@"); return sb.toString(); 128 } 129 130 int getHunkType(boolean reverse) { 131 if (reverse) { 132 if (hunkType == ADDED) 133 return DELETED; 134 if (hunkType == DELETED) 135 return ADDED; 136 } 137 return hunkType; 138 } 139 140 void setHunkType(int hunkType) { 141 this.hunkType = hunkType; 142 } 143 144 public String [] getLines() { 145 return fLines; 146 } 147 148 153 void setParent(FileDiff diff) { 154 if (fParent == diff) 155 return; 156 if (fParent != null) 157 fParent.remove(this); 158 fParent = diff; 159 } 160 161 public FileDiff getParent() { 162 return fParent; 163 } 164 165 170 public boolean tryPatch(PatchConfiguration configuration, List lines, int shift) { 171 boolean reverse = configuration.isReversed(); 172 int pos= getStart(reverse) + shift; 173 int deleteMatches= 0; 174 for (int i= 0; i < fLines.length; i++) { 175 String s= fLines[i]; 176 Assert.isTrue(s.length() > 0); 177 String line= s.substring(1); 178 char controlChar= s.charAt(0); 179 if (controlChar == ' ') { while (true) { 181 if (pos < 0 || pos >= lines.size()) 182 return false; 183 if (linesMatch(configuration, line, (String ) lines.get(pos))) { 184 pos++; 185 break; 186 } 187 return false; 188 } 189 } else if (isDeletedDelimeter(controlChar, reverse)) { 190 while (true) { 192 if (pos < 0 || pos >= lines.size()) 193 return false; 194 if (linesMatch(configuration, line, (String ) lines.get(pos))) { 195 deleteMatches++; 196 pos++; 197 break; 198 } 199 200 204 return false; 206 } 208 } else if (isAddedDelimeter(controlChar, reverse)) { 209 } else 212 Assert.isTrue(false, "tryPatch: unknown control character: " + controlChar); } 214 return true; 215 } 216 217 int getStart(boolean reverse) { 218 if (reverse) { 219 return fNewStart; 220 } 221 return fOldStart; 222 } 223 224 private int getLength(boolean reverse) { 225 if (reverse) { 226 return fNewLength; 227 } 228 return fOldLength; 229 } 230 231 private int getShift(boolean reverse) { 232 if (reverse) { 233 return fOldLength - fNewLength; 234 } 235 return fNewLength - fOldLength; 236 } 237 238 int doPatch(PatchConfiguration configuration, List lines, int shift) { 239 boolean reverse = configuration.isReversed(); 240 int pos = getStart(reverse) + shift; 241 for (int i= 0; i < fLines.length; i++) { 242 String s= fLines[i]; 243 Assert.isTrue(s.length() > 0); 244 String line= s.substring(1); 245 char controlChar= s.charAt(0); 246 if (controlChar == ' ') { while (true) { 248 Assert.isTrue(pos < lines.size(), "doPatch: inconsistency in context"); if (linesMatch(configuration, line, (String ) lines.get(pos))) { 250 pos++; 251 break; 252 } 253 pos++; 254 } 255 } else if (isDeletedDelimeter(controlChar, reverse)) { 256 while (true) { 258 Assert.isTrue(pos < lines.size(), "doPatch: inconsistency in deleted lines"); if (linesMatch(configuration, line, (String ) lines.get(pos))) { 260 break; 261 } 262 pos++; 263 } 264 lines.remove(pos); 265 } else if (isAddedDelimeter(controlChar, reverse)) { 266 if (getLength(reverse) == 0 && pos+1 < lines.size()) 268 lines.add(pos+1, line); 269 else 270 lines.add(pos, line); 271 pos++; 272 } else 273 Assert.isTrue(false, "doPatch: unknown control character: " + controlChar); } 275 return getShift(reverse); 276 } 277 278 private boolean isDeletedDelimeter(char controlChar, boolean reverse) { 279 return (!reverse && controlChar == '-') || (reverse && controlChar == '+'); 280 } 281 282 private boolean isAddedDelimeter(char controlChar, boolean reverse) { 283 return (reverse && controlChar == '-') || (!reverse && controlChar == '+'); 284 } 285 286 290 private boolean linesMatch(PatchConfiguration configuration, String line1, String line2) { 291 if (configuration.isIgnoreWhitespace()) 292 return stripWhiteSpace(line1).equals(stripWhiteSpace(line2)); 293 if (isIgnoreLineDelimiter()) { 294 int l1= Patcher.length(line1); 295 int l2= Patcher.length(line2); 296 if (l1 != l2) 297 return false; 298 return line1.regionMatches(0, line2, 0, l1); 299 } 300 return line1.equals(line2); 301 } 302 303 private boolean isIgnoreLineDelimiter() { 304 return true; 305 } 306 307 311 private String stripWhiteSpace(String s) { 312 StringBuffer sb= new StringBuffer (); 313 int l= s.length(); 314 for (int i= 0; i < l; i++) { 315 char c= s.charAt(i); 316 if (!Character.isWhitespace(c)) 317 sb.append(c); 318 } 319 return sb.toString(); 320 } 321 322 public String getContents(boolean isAfterState, boolean reverse) { 323 StringBuffer result= new StringBuffer (); 324 for (int i= 0; i<fLines.length; i++) { 325 String line= fLines[i]; 326 String rest= line.substring(1); 327 char c = line.charAt(0); 328 if (c == ' ') { 329 result.append(rest); 330 } else if (isDeletedDelimeter(c, reverse) && !isAfterState) { 331 result.append(rest); 332 } else if (isAddedDelimeter(c, reverse) && isAfterState) { 333 result.append(rest); 334 } 335 } 336 return result.toString(); 337 } 338 } 339 | Popular Tags |