/**
 * @author  Dirk Brodersen
 *
 * Ein FilterReader, der Java-Klassen um Kommentare erleichtert. Es werden
 * alle Kommentare innerhalb von /* - Zeichen entfernt. Zeilenweise Kommentare
 * mit "//" bleiben erhalten.
 */
package javacodebook.io.commentfilter;

import java.io.*;

public class CommentFilterReader extends java.io.FilterReader {

    //Flag, um festzustellen, ob gerade Zeichen innerhalb oder
    //ausserhalb eines Kommentars gelesen werden
    private boolean insideComment = false;
    //das letzte gelesene Zeichen
    private char prevChar;
    //Dieses Flag wird benötigt, um über zwei Lesevorgänge hinweg einen
    //Kommentar zuverlässig zu erkennen
    private boolean startComment = false;

    public CommentFilterReader(Reader in) {
        super(in);
    }

    public int read() throws java.io.IOException {
        char[] buf = new char[1];
        return read(buf, 0, 1) == -1 ? -1 : buf[0];
    }

    public int read(char[] buffer, int offset, int length)
    throws java.io.IOException {
        int charsRead = 0;

        while(charsRead == 0) {
            charsRead = in.read(buffer, offset, length);
            if(charsRead == -1)
                return -1;
            int lastNonComment = offset;

            for(int i = 0; i < offset + charsRead; i++) {
                if(insideComment) {
                    if(buffer[i] == '/' && prevChar == '*') {
                        insideComment = false;
                        startComment = false;
                    }
                } else {
                    if(buffer[i] == '/') {
                        if(i < buffer.length -1) {//Noch nicht am Ende buffer
                            if(buffer[i+1] == '*') {
                                insideComment = true;
                                continue; //dieses Zeichen auch ignorieren
                            }
                        }
                        else //am Ende des Buffers angekommen
                            startComment = true;
                    } else if(startComment && buffer[i] != '*') {
                        //Wurde im alten buffer ein '/' gefunden, so muss im
                        //neuen geschaut werden, ob der noch geschrieben werden
                        //muss
                        buffer[lastNonComment] = prevChar;
                        lastNonComment++;
                        startComment = false;
                    }
                    //das aktuelle Zeichen schreiben, wenn es kein '/' war
                    if(!startComment) {
                        buffer[lastNonComment] = buffer[i];
                        lastNonComment++;
                    }
                }
                prevChar = buffer[i];
            }
            charsRead = lastNonComment - offset;
        }
        return charsRead;
    }

}
