001package org.unix4j.unix.sed;
002
003import org.unix4j.line.Line;
004import org.unix4j.line.SimpleLine;
005import org.unix4j.processor.LineProcessor;
006import org.unix4j.util.StringUtil;
007
008class TranslateProcessor extends AbstractSedProcessor {
009        private final CharMap charMap;
010        public TranslateProcessor(Command command, SedArguments args, LineProcessor output) {
011                super(command, args, output);
012                this.charMap = new CharMap(args.getString1(), args.getString2());
013        }
014        public TranslateProcessor(Command command, String script, SedArguments args, LineProcessor output) {
015                this(command, deriveArgs(command, script, args), output);
016        }
017
018        private static SedArguments deriveArgs(Command command, String script, SedArguments args) {
019                final int start = StringUtil.findStartTrimWhitespace(script) + 1;
020                final int mid = indexOfNextDelimiter(script, start);
021                final int end = indexOfNextDelimiter(script, mid);
022                if (mid < 0 || end < 0) {
023                        throw new IllegalArgumentException("invalid script for sed " + command + " command: " + script);
024                }
025                final int scriptEnd = StringUtil.findEndTrimWhitespace(script);
026                if (end + 1 < scriptEnd) {
027                        throw new IllegalArgumentException("non-whitespace characters found after " + command + " command in sed script: " + script);
028                }
029                args.setString1(script.substring(start + 1, mid));
030                args.setString2(script.substring(mid + 1, end));
031                return args;
032        }
033        @Override
034        public boolean processLine(Line line) {
035                char[] changed = null;
036                final int len = line.getContentLength();//or whole line length?
037                for (int i = 0; i < len; i++) {
038                        final char src = line.charAt(i);
039                        final char dst = charMap.map(src);
040                        if (dst != 0) {
041                                if (changed == null) {
042                                        changed = new char[len];
043                                        for (int j = 0; j < i; j++) {
044                                                changed[j] = line.charAt(j);
045                                        }
046                                }
047                                changed[i] = dst;
048                        } else {
049                                if (changed != null) {
050                                        changed[i] = src;
051                                }
052                        }
053                }
054                if (changed != null) {
055                        final Line changedLine = new SimpleLine(String.valueOf(changed), line.getLineEnding());
056                        return output.processLine(changedLine);
057                } else {
058                        return output.processLine(line);
059                }
060        }
061}