27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen/*
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen * CDDL HEADER START
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen *
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen * The contents of this file are subject to the terms of the
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen * Common Development and Distribution License (the "License").
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen * You may not use this file except in compliance with the License.
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen *
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen * See LICENSE.txt included in this distribution for the specific
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen * language governing permissions and limitations under the License.
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen *
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen * When distributing Covered Code, include this CDDL HEADER in each
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen * file and include the License file at LICENSE.txt.
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen * If applicable, add the following below this CDDL HEADER, with the
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen * fields enclosed by brackets "[]" replaced with your own identifying
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen * information: Portions Copyright [yyyy] [name of copyright owner]
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen *
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen * CDDL HEADER END
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen */
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen/*
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen * Use is subject to license terms.
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen */
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlenpackage org.opensolaris.opengrok.analysis;
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlenimport java.io.FilterReader;
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlenimport java.io.IOException;
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlenimport java.io.Reader;
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlenimport org.opensolaris.opengrok.configuration.Project;
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen/**
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen * Wrapper around Reader to expand tabs to spaces in the input.
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen */
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlenpublic class ExpandTabsReader extends FilterReader {
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen /** The size of tabs. */
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen private final int tabSize;
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen /**
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen * The position on the current line. Used to decide how many spaces to
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen * insert to fill up to the next tab stop.
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen */
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen private int pos;
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen /**
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen * Number of spaces to insert (as replacement for a tab) before reading
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen * more from the underlying stream.
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen */
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen private int spacesToInsert;
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen /**
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen * Create a new ExpandTabsReader to expand tabs to spaces.
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen *
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen * @param in the original input source
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen * @param tabSize the size of tabs
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen */
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen ExpandTabsReader(Reader in, int tabSize) {
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen super(in);
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen this.tabSize = tabSize;
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen }
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen /**
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen * Wrap a reader in an ExpandTabsReader if the project has custom tab
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen * size settings.
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen *
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen * @param in the reader to wrap
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen * @param p the project
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen * @return {@code in} if the project doesn't have custom tab settings;
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen * otherwise, an {@code ExpandTabsReader} that wraps {@code in} and expands
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen * tabs as defined by the project's settings
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen */
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen public static Reader wrap(Reader in, Project p) {
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen if (p != null && p.hasTabSizeSetting()) {
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen return new ExpandTabsReader(in, p.getTabSize());
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen } else {
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen return in;
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen }
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen }
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen @Override
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen public int read() throws IOException {
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen if (spacesToInsert > 0) {
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen pos++;
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen spacesToInsert--;
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen return ' ';
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen }
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen int c = super.read();
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen if (c == '\t') {
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen // Fill up with spaces up to the next tab stop
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen int spaces = tabSize - (pos % tabSize);
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen pos++;
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen spacesToInsert = spaces - 1;
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen return ' ';
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen }
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen if (c == '\n' || c == '\r') {
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen // Reset position on new line
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen pos = 0;
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen } else {
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen pos++;
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen }
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen return c;
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen }
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen @Override
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen public int read(char[] cbuf, int off, int len) throws IOException {
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen for (int i = 0; i < len; i++) {
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen int c = read();
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen if (c == -1) {
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen return (i > 0 ? i : -1);
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen }
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen cbuf[off + i] = (char) c;
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen }
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen return len;
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen }
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen @Override
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen public long skip(long n) throws IOException {
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen if (n < 0L) {
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen throw new IllegalArgumentException("n is negative");
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen }
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen long skipped = 0;
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen for (long l = 0; l < n; l++) {
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen int c = read();
8554c95b387bb1bfdfb517861a0d505625e56426Knut Anders Hatlen if (c == -1) {
8554c95b387bb1bfdfb517861a0d505625e56426Knut Anders Hatlen break;
8554c95b387bb1bfdfb517861a0d505625e56426Knut Anders Hatlen }
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen skipped++;
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen }
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen return skipped;
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen }
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen @Override
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen public boolean markSupported() {
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen // Support for mark/reset has not been implemented.
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen return false;
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen }
27fefc4a4ce87f5424c87bf7f4c772efa1c1b8a8Knut Anders Hatlen}