Home | History | Annotate | Download | only in utils
      1 /*
      2  * Copyright (C) 2013 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.inputmethod.latin.utils;
     18 
     19 import com.android.inputmethod.annotations.UsedForTesting;
     20 
     21 import java.io.EOFException;
     22 import java.io.IOException;
     23 import java.io.LineNumberReader;
     24 
     25 @UsedForTesting
     26 public class Base64Reader {
     27     private final LineNumberReader mReader;
     28 
     29     private String mLine;
     30     private int mCharPos;
     31     private int mByteCount;
     32 
     33     @UsedForTesting
     34     public Base64Reader(final LineNumberReader reader) {
     35         mReader = reader;
     36         reset();
     37     }
     38 
     39     @UsedForTesting
     40     public void reset() {
     41         mLine = null;
     42         mCharPos = 0;
     43         mByteCount = 0;
     44     }
     45 
     46     @UsedForTesting
     47     public int getLineNumber() {
     48         return mReader.getLineNumber();
     49     }
     50 
     51     @UsedForTesting
     52     public int getByteCount() {
     53         return mByteCount;
     54     }
     55 
     56     private void fillBuffer() throws IOException {
     57         if (mLine == null || mCharPos >= mLine.length()) {
     58             mLine = mReader.readLine();
     59             mCharPos = 0;
     60         }
     61         if (mLine == null) {
     62             throw new EOFException();
     63         }
     64     }
     65 
     66     private int peekUint8() throws IOException {
     67         fillBuffer();
     68         final char c = mLine.charAt(mCharPos);
     69         if (c >= 'A' && c <= 'Z')
     70             return c - 'A' + 0;
     71         if (c >= 'a' && c <= 'z')
     72             return c - 'a' + 26;
     73         if (c >= '0' && c <= '9')
     74             return c - '0' + 52;
     75         if (c == '+')
     76             return 62;
     77         if (c == '/')
     78             return 63;
     79         if (c == '=')
     80             return 0;
     81         throw new RuntimeException("Unknown character '" + c + "' in base64 at line "
     82                 + mReader.getLineNumber());
     83     }
     84 
     85     private int getUint8() throws IOException {
     86         final int value = peekUint8();
     87         mCharPos++;
     88         return value;
     89     }
     90 
     91     @UsedForTesting
     92     public int readUint8() throws IOException {
     93         final int value1, value2;
     94         switch (mByteCount % 3) {
     95         case 0:
     96             value1 = getUint8() << 2;
     97             value2 = value1 | (peekUint8() >> 4);
     98             break;
     99         case 1:
    100             value1 = (getUint8() & 0x0f) << 4;
    101             value2 = value1 | (peekUint8() >> 2);
    102             break;
    103         default:
    104             value1 = (getUint8() & 0x03) << 6;
    105             value2 = value1 | getUint8();
    106             break;
    107         }
    108         mByteCount++;
    109         return value2;
    110     }
    111 
    112     @UsedForTesting
    113     public short readInt16() throws IOException {
    114         final int data = readUint8() << 8;
    115         return (short)(data | readUint8());
    116     }
    117 }
    118