    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *      http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 * Unless required by applicable law or agreed to in writing, software
    012 * distributed under the License is distributed on an "AS IS" BASIS,
    013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 * See the License for the specific language governing permissions and
    015 * limitations under the License.
    016 */
    017package org.apache.commons.io.input;
    018
    019import java.io.FilterReader;
    020import java.io.IOException;
    021import java.io.Reader;
    022
    023/**
    024 * A filter reader that filters out characters where subclasses decide which characters to filter out.
    025 */
    026public abstract class AbstractCharacterFilterReader extends FilterReader {
    027
    028    /**
    029     * Constructs a new reader.
    030     *
    031     * @param reader
    032     *            the reader to filter
    033     */
    034    protected AbstractCharacterFilterReader(final Reader reader) {
    035        super(reader);
    036    }
    037
    038    @Override
    039    public int read() throws IOException {
    040        int ch;
    041        do {
    042            ch = in.read();
    043        } while (filter(ch));
    044        return ch;
    045    }
    046
    047    /**
    048     * Returns true if the given character should be filtered out, false to keep the character.
    049     *
    050     * @param ch
    051     *            the character to test.
    052     * @return true if the given character should be filtered out, false to keep the character.
    053     */
    054    protected abstract boolean filter(int ch);
    055
    056    @Override
    057    public int read(final char[] cbuf, final int off, final int len) throws IOException {
    058        final int read = super.read(cbuf, off, len);
    059        if (read == -1) {
    060            return -1;
    061        }
    062        int pos = off - 1;
    063        for (int readPos = off; readPos < off + read; readPos++) {
    064            if (filter(cbuf[readPos])) {
    065                continue;
    066            }
    067            pos++;
    068            if (pos < readPos) {
    069                cbuf[pos] = cbuf[readPos];
    070            }
    071        }
    072        return pos - off + 1;
    073    }
    074}