001/* 002 * Sonar, open source software quality management tool. 003 * Copyright (C) 2008-2012 SonarSource 004 * mailto:contact AT sonarsource DOT com 005 * 006 * Sonar is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 3 of the License, or (at your option) any later version. 010 * 011 * Sonar is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public 017 * License along with Sonar; if not, write to the Free Software 018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 019 */ 020package org.sonar.plugins.core.timemachine.tracking; 021 022/** 023 * Equivalence function for {@link StringText}. 024 */ 025public abstract class StringTextComparator implements SequenceComparator<StringText> { 026 027 /** 028 * Ignores all whitespace. 029 */ 030 public static final StringTextComparator IGNORE_WHITESPACE = new StringTextComparator() { 031 032 public boolean equals(StringText a, int ai, StringText b, int bi) { 033 ai++; 034 bi++; 035 int as = a.lines.get(ai); 036 int bs = b.lines.get(bi); 037 int ae = a.lines.get(ai + 1); 038 int be = b.lines.get(bi + 1); 039 ae = trimTrailingWhitespace(a.content, as, ae); 040 be = trimTrailingWhitespace(b.content, bs, be); 041 while ((as < ae) && (bs < be)) { 042 char ac = a.content.charAt(as); 043 char bc = b.content.charAt(bs); 044 while ((as < ae - 1) && (Character.isWhitespace(ac))) { 045 as++; 046 ac = a.content.charAt(as); 047 } 048 while ((bs < be - 1) && (Character.isWhitespace(bc))) { 049 bs++; 050 bc = b.content.charAt(bs); 051 } 052 if (ac != bc) { 053 return false; 054 } 055 as++; 056 bs++; 057 } 058 return (as == ae) && (bs == be); 059 } 060 061 @Override 062 protected int hashRegion(String content, int start, int end) { 063 int hash = 5381; 064 for (; start < end; start++) { 065 char c = content.charAt(start); 066 if (!Character.isWhitespace(c)) { 067 hash = ((hash << 5) + hash) + (c & 0xff); 068 } 069 } 070 return hash; 071 } 072 073 }; 074 075 public int hash(StringText seq, int line) { 076 final int begin = seq.lines.get(line + 1); 077 final int end = seq.lines.get(line + 2); 078 return hashRegion(seq.content, begin, end); 079 } 080 081 protected abstract int hashRegion(String content, int start, int end); 082 083 public static int trimTrailingWhitespace(String content, int start, int end) { 084 end--; 085 while (start <= end && Character.isWhitespace(content.charAt(end))) { 086 end--; 087 } 088 return end + 1; 089 } 090 091}