001package org.unix4j.unix.sed;
002
003import java.util.HashMap;
004import java.util.Map;
005
006/**
007 * A map from char to char. The mappings for the most common 256 source
008 * characters are simply kept in a char array. For all other more exotic source
009 * characters, a proper hash map is used to store the mapping.
010 */
011class CharMap {
012
013        private final char[] map = new char[256];
014        private final Map<Character, Character> extendedMap = new HashMap<Character, Character>();
015
016        /**
017         * Creates a char map with the given source and destination characters. If
018         * the strings do not have the same length, subsequent characters in the
019         * longer string are ignored. The first mapping is defined as
020         * {@code source[0] --> destination[0]}, all other mappings in an analogous
021         * way with matching character indices in the two strings.
022         * 
023         * @param source
024         *            source characters
025         * @param destination
026         *            destination characters
027         * @throws IllegalArgumentException
028         *             if any of the destination characters is the zero character
029         */
030        public CharMap(String source, String destination) {
031                add(source, destination);
032        }
033
034        /**
035         * Adds the given source and destination characters to this char map.. If
036         * the strings do not have the same length, subsequent characters in the
037         * longer string are ignored. The first mapping is defined as
038         * {@code source[0] --> destination[0]}, all other mappings in an analogous
039         * way with matching character indices in the two strings.
040         * 
041         * @param source
042         *            source characters
043         * @param destination
044         *            destination characters
045         * @throws IllegalArgumentException
046         *             if any of the destination characters is the zero character
047         */
048        public void add(String source, String destination) {
049                final int len = Math.min(source.length(), destination.length());
050                for (int i = 0; i < len; i++) {
051                        add(source.charAt(i), destination.charAt(i));
052                }
053        }
054
055        /**
056         * Adds the given mapping {@code source --> destination} to this char map.
057         * 
058         * @param source
059         *            source character
060         * @param destination
061         *            destination character
062         * @throws IllegalArgumentException
063         *             if the destination character is the zero character
064         */
065        public void add(char source, char destination) {
066                if (destination == 0) {
067                        throw new IllegalArgumentException("cannot map to zero character");
068                }
069                if (source < 256) {
070                        map[source] = destination;
071                } else {
072                        extendedMap.put(source, destination);
073                }
074        }
075
076        public char map(char source) {
077                if (source < 256) {
078                        return map[source];
079                }
080                final Character mapped = extendedMap.get(source);
081                return mapped == null ? 0 : mapped.charValue();
082        }
083}