• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
Base64Reader(final LineNumberReader reader)34     public Base64Reader(final LineNumberReader reader) {
35         mReader = reader;
36         reset();
37     }
38 
39     @UsedForTesting
reset()40     public void reset() {
41         mLine = null;
42         mCharPos = 0;
43         mByteCount = 0;
44     }
45 
46     @UsedForTesting
getLineNumber()47     public int getLineNumber() {
48         return mReader.getLineNumber();
49     }
50 
51     @UsedForTesting
getByteCount()52     public int getByteCount() {
53         return mByteCount;
54     }
55 
fillBuffer()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 
peekUint8()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 
getUint8()85     private int getUint8() throws IOException {
86         final int value = peekUint8();
87         mCharPos++;
88         return value;
89     }
90 
91     @UsedForTesting
readUint8()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
readInt16()113     public short readInt16() throws IOException {
114         final int data = readUint8() << 8;
115         return (short)(data | readUint8());
116     }
117 }
118