/* * Copyright (c) 2007 Mozilla Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ package nu.validator.source; /** * Immutable source location with zero-based indexes. * Cannot point to a line break. * * @version $Id$ * @author hsivonen */ public final class Location implements Comparable<Location>, Cloneable { private final SourceCode owner; private final int line; private final int column; /** * @param line * @param column */ Location(final SourceCode owner, int line, int column) { this.owner = owner; if (line < 0) { line = 0; column = 0; } else if (column < 0) { line--; if (line < 0) { line = 0; column = 0; } else { column = owner.getLine(line).getBufferLength(); } } this.line = line; this.column = column; } @Override public int compareTo(Location o) { if (this.line < o.line) { return -1; } else if (this.line > o.line) { return 1; } else { if (this.column < o.column) { return -1; } else if (this.column > o.column) { return 1; } else { return 0; } } } /** * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (obj instanceof Location) { Location loc = (Location) obj; return this.line == loc.line && this.column == loc.column; } else { return false; } } /** * Returns the column. * * @return the column */ public int getColumn() { return column; } /** * Returns the line. * * @return the line */ public int getLine() { return line; } /** * * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return (line << 16) + column; } Location next() { return step(1); } Location prev() { return step(-1); } Location step(int offset) { int newLine = line; int newColumn = column; if (offset > 0) { for (int i = 0; i < offset; i++) { if (newLine == owner.getNumberOfLines()) { break; } newColumn++; Line sourceLine = owner.getLine(newLine); if (newColumn > sourceLine.getBufferLength()) { newLine++; newColumn = 0; } } return new Location(owner, newLine, newColumn); } if (offset < 0) { offset = -offset; for (int i = 0; i < offset; i++) { if (newLine == 0 && newColumn == 0) { break; } newColumn--; if (newColumn == -1) { newLine--; newColumn = owner.getLine(newLine).getBufferLength(); } } return new Location(owner, newLine, newColumn); } else { return this; } } /** * @see java.lang.Object#toString() */ @Override public String toString() { return line + ", " + column; } }