14fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy/****************************************************************
24fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Licensed to the Apache Software Foundation (ASF) under one   *
34fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * or more contributor license agreements.  See the NOTICE file *
44fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * distributed with this work for additional information        *
54fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * regarding copyright ownership.  The ASF licenses this file   *
64fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * to you under the Apache License, Version 2.0 (the            *
74fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * "License"); you may not use this file except in compliance   *
84fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * with the License.  You may obtain a copy of the License at   *
94fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy *                                                              *
104fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy *   http://www.apache.org/licenses/LICENSE-2.0                 *
114fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy *                                                              *
124fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Unless required by applicable law or agreed to in writing,   *
134fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * software distributed under the License is distributed on an  *
144fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
154fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * KIND, either express or implied.  See the License for the    *
164fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * specific language governing permissions and limitations      *
174fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * under the License.                                           *
184fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy ****************************************************************/
194fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
204fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedypackage org.apache.james.mime4j.decoder;
214fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
224fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedyimport java.io.IOException;
234fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedyimport java.io.InputStream;
244fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
254fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy//BEGIN android-changed: Stubbing out logging
264fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedyimport org.apache.james.mime4j.Log;
274fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedyimport org.apache.james.mime4j.LogFactory;
284fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy//END android-changed
294fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
304fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy/**
314fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Performs Quoted-Printable decoding on an underlying stream.
324fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy *
334fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy *
344fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy *
354fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @version $Id: QuotedPrintableInputStream.java,v 1.3 2004/11/29 13:15:47 ntherning Exp $
364fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */
374fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedypublic class QuotedPrintableInputStream extends InputStream {
384fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    private static Log log = LogFactory.getLog(QuotedPrintableInputStream.class);
394fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
404fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    private InputStream stream;
414fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    ByteQueue byteq = new ByteQueue();
424fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    ByteQueue pushbackq = new ByteQueue();
434fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    private byte state = 0;
444fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
454fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    public QuotedPrintableInputStream(InputStream stream) {
464fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        this.stream = stream;
474fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    }
484fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
494fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    /**
504fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * Closes the underlying stream.
514fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     *
524fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @throws IOException on I/O errors.
534fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     */
544fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    public void close() throws IOException {
554fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        stream.close();
564fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    }
574fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
584fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    public int read() throws IOException {
594fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        fillBuffer();
604fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        if (byteq.count() == 0)
614fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            return -1;
624fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        else {
634fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            byte val = byteq.dequeue();
644fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            if (val >= 0)
654fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                return val;
664fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            else
674fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                return val & 0xFF;
684fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        }
694fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    }
704fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
714fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    /**
724fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * Pulls bytes out of the underlying stream and places them in the
734fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * pushback queue.  This is necessary (vs. reading from the
744fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * underlying stream directly) to detect and filter out "transport
754fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * padding" whitespace, i.e., all whitespace that appears immediately
764fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * before a CRLF.
774fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     *
784fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @throws IOException Underlying stream threw IOException.
794fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     */
804fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    private void populatePushbackQueue() throws IOException {
814fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        //Debug.verify(pushbackq.count() == 0, "PopulatePushbackQueue called when pushback queue was not empty!");
824fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
834fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        if (pushbackq.count() != 0)
844fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            return;
854fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
864fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        while (true) {
874fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            int i = stream.read();
884fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            switch (i) {
894fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                case -1:
904fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                    // stream is done
914fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                    pushbackq.clear();  // discard any whitespace preceding EOF
924fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                    return;
934fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                case ' ':
944fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                case '\t':
954fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                    pushbackq.enqueue((byte)i);
964fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                    break;
974fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                case '\r':
984fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                case '\n':
994fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                    pushbackq.clear();  // discard any whitespace preceding EOL
1004fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                    pushbackq.enqueue((byte)i);
1014fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                    return;
1024fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                default:
1034fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                    pushbackq.enqueue((byte)i);
1044fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                    return;
1054fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            }
1064fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        }
1074fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    }
1084fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
1094fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    /**
1104fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * Causes the pushback queue to get populated if it is empty, then
1114fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * consumes and decodes bytes out of it until one or more bytes are
1124fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * in the byte queue.  This decoding step performs the actual QP
1134fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * decoding.
1144fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     *
1154fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @throws IOException Underlying stream threw IOException.
1164fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     */
1174fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    private void fillBuffer() throws IOException {
1184fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        byte msdChar = 0;  // first digit of escaped num
1194fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        while (byteq.count() == 0) {
1204fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            if (pushbackq.count() == 0) {
1214fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                populatePushbackQueue();
1224fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                if (pushbackq.count() == 0)
1234fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                    return;
1244fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            }
1254fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
1264fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            byte b = (byte)pushbackq.dequeue();
1274fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
1284fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            switch (state) {
1294fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                case 0:  // start state, no bytes pending
1304fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                    if (b != '=') {
1314fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                        byteq.enqueue(b);
1324fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                        break;  // state remains 0
1334fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                    } else {
1344fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                        state = 1;
1354fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                        break;
1364fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                    }
1374fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                case 1:  // encountered "=" so far
1384fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                    if (b == '\r') {
1394fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                        state = 2;
1404fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                        break;
1414fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                    } else if ((b >= '0' && b <= '9') || (b >= 'A' && b <= 'F') || (b >= 'a' && b <= 'f')) {
1424fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                        state = 3;
1434fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                        msdChar = b;  // save until next digit encountered
1444fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                        break;
1454fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                    } else if (b == '=') {
1464fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                        /*
1474fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                         * Special case when == is encountered.
1484fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                         * Emit one = and stay in this state.
1494fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                         */
1504fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                        if (log.isWarnEnabled()) {
1514fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                            log.warn("Malformed MIME; got ==");
1524fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                        }
1534fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                        byteq.enqueue((byte)'=');
1544fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                        break;
1554fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                    } else {
1564fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                        if (log.isWarnEnabled()) {
1574fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                            log.warn("Malformed MIME; expected \\r or "
1584fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                                    + "[0-9A-Z], got " + b);
1594fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                        }
1604fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                        state = 0;
1614fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                        byteq.enqueue((byte)'=');
1624fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                        byteq.enqueue(b);
1634fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                        break;
1644fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                    }
1654fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                case 2:  // encountered "=\r" so far
1664fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                    if (b == '\n') {
1674fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                        state = 0;
1684fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                        break;
1694fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                    } else {
1704fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                        if (log.isWarnEnabled()) {
1714fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                            log.warn("Malformed MIME; expected "
1724fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                                    + (int)'\n' + ", got " + b);
1734fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                        }
1744fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                        state = 0;
1754fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                        byteq.enqueue((byte)'=');
1764fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                        byteq.enqueue((byte)'\r');
1774fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                        byteq.enqueue(b);
1784fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                        break;
1794fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                    }
1804fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                case 3:  // encountered =<digit> so far; expecting another <digit> to complete the octet
1814fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                    if ((b >= '0' && b <= '9') || (b >= 'A' && b <= 'F') || (b >= 'a' && b <= 'f')) {
1824fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                        byte msd = asciiCharToNumericValue(msdChar);
1834fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                        byte low = asciiCharToNumericValue(b);
1844fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                        state = 0;
1854fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                        byteq.enqueue((byte)((msd << 4) | low));
1864fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                        break;
1874fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                    } else {
1884fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                        if (log.isWarnEnabled()) {
1894fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                            log.warn("Malformed MIME; expected "
1904fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                                     + "[0-9A-Z], got " + b);
1914fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                        }
1924fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                        state = 0;
1934fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                        byteq.enqueue((byte)'=');
1944fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                        byteq.enqueue(msdChar);
1954fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                        byteq.enqueue(b);
1964fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                        break;
1974fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                    }
1984fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                default:  // should never happen
1994fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                    log.error("Illegal state: " + state);
2004fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                    state = 0;
2014fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                    byteq.enqueue(b);
2024fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                    break;
2034fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            }
2044fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        }
2054fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    }
2064fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
2074fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    /**
2084fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * Converts '0' => 0, 'A' => 10, etc.
2094fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @param c ASCII character value.
2104fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @return Numeric value of hexadecimal character.
2114fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     */
2124fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    private byte asciiCharToNumericValue(byte c) {
2134fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        if (c >= '0' && c <= '9') {
2144fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            return (byte)(c - '0');
2154fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        } else if (c >= 'A' && c <= 'Z') {
2164fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            return (byte)(0xA + (c - 'A'));
2174fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        } else if (c >= 'a' && c <= 'z') {
2184fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            return (byte)(0xA + (c - 'a'));
2194fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        } else {
2204fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            /*
2214fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy             * This should never happen since all calls to this method
2224fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy             * are preceded by a check that c is in [0-9A-Za-z]
2234fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy             */
2244fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            throw new IllegalArgumentException((char) c
2254fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                    + " is not a hexadecimal digit");
2264fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        }
2274fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    }
2284fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
2294fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy}
230