001package org.unix4j.unix.tail;
002
003import java.util.LinkedList;
004
005import org.unix4j.context.ExecutionContext;
006import org.unix4j.line.Line;
007import org.unix4j.line.SimpleLine;
008import org.unix4j.processor.LineProcessor;
009import org.unix4j.util.Counter;
010
011public class TailCharsFromEndProcessor extends AbstractTailProcessor {
012        
013        private final Counter counter = new Counter();
014        private final LinkedList<Line> tailLines = new LinkedList<Line>();
015
016    @Override
017    public void resetCountersAndFlush() {
018        final LineProcessor output = getOutput();
019        boolean more = true;
020        if (counter.getCount() > count) {
021            final Line line = tailLines.removeFirst();
022            final int offset = (int)(counter.getCount() - count);
023            final Line cutLine = SimpleLine.subLine(line, offset, line.length(), false);
024            more = output.processLine(cutLine);
025        }
026        while (!tailLines.isEmpty() && more) {
027            more = output.processLine(tailLines.removeFirst());//remove to free memory
028        }
029        counter.reset();
030        tailLines.clear();
031    }
032
033    public TailCharsFromEndProcessor(TailCommand command, ExecutionContext context, LineProcessor output) {
034                super(command, context, output);
035        }
036
037        @Override
038        public boolean processLine(Line line) {
039                tailLines.add(line);
040                if (counter.increment(line.length()) > count) {
041                        long firstLen = tailLines.getFirst().length();
042                        while (counter.getCount() - firstLen >= count) {
043                                tailLines.removeFirst();
044                                counter.decrement(firstLen);
045                                firstLen = tailLines.isEmpty() ? counter.getCount() : tailLines.getFirst().length();
046                        }
047                }
048                return true;//we want all lines
049        }
050
051        @Override
052        public void finish() {
053                final LineProcessor output = getOutput();
054        resetCountersAndFlush();
055                output.finish();
056        }
057        
058}