Decode another block of input data. @return true if the state machine is still healthy. false if bad base-64 data has been detected in the input stream.
(byte[] input, int offset, int len, boolean finish)
| 223 | * detected in the input stream. |
| 224 | */ |
| 225 | public boolean process(byte[] input, int offset, int len, boolean finish) { |
| 226 | if (this.state == 6) return false; |
| 227 | |
| 228 | int p = offset; |
| 229 | len += offset; |
| 230 | |
| 231 | // Using local variables makes the decoder about 12% |
| 232 | // faster than if we manipulate the member variables in |
| 233 | // the loop. (Even alphabet makes a measurable |
| 234 | // difference, which is somewhat surprising to me since |
| 235 | // the member variable is final.) |
| 236 | int state = this.state; |
| 237 | int value = this.value; |
| 238 | int op = 0; |
| 239 | final byte[] output = this.output; |
| 240 | final int[] alphabet = this.alphabet; |
| 241 | |
| 242 | while (p < len) { |
| 243 | // Try the fast path: we're starting a new tuple and the |
| 244 | // next four bytes of the input stream are all data |
| 245 | // bytes. This corresponds to going through states |
| 246 | // 0-1-2-3-0. We expect to use this method for most of |
| 247 | // the data. |
| 248 | // |
| 249 | // If any of the next four bytes of input are non-data |
| 250 | // (whitespace, etc.), value will end up negative. (All |
| 251 | // the non-data values in decode are small negative |
| 252 | // numbers, so shifting any of them up and or'ing them |
| 253 | // together will result in a value with its top bit set.) |
| 254 | // |
| 255 | // You can remove this whole block and the output should |
| 256 | // be the same, just slower. |
| 257 | if (state == 0) { |
| 258 | while (p + 4 <= len && |
| 259 | (value = ((alphabet[input[p] & 0xff] << 18) | |
| 260 | (alphabet[input[p + 1] & 0xff] << 12) | |
| 261 | (alphabet[input[p + 2] & 0xff] << 6) | |
| 262 | (alphabet[input[p + 3] & 0xff]))) >= 0) { |
| 263 | output[op + 2] = (byte) value; |
| 264 | output[op + 1] = (byte) (value >> 8); |
| 265 | output[op] = (byte) (value >> 16); |
| 266 | op += 3; |
| 267 | p += 4; |
| 268 | } |
| 269 | if (p >= len) break; |
| 270 | } |
| 271 | |
| 272 | // The fast path isn't available -- either we've read a |
| 273 | // partial tuple, or the next four input bytes aren't all |
| 274 | // data, or whatever. Fall back to the slower state |
| 275 | // machine implementation. |
| 276 | |
| 277 | int d = alphabet[input[p++] & 0xff]; |
| 278 | |
| 279 | switch (state) { |
| 280 | case 0: |
| 281 | if (d >= 0) { |
| 282 | value = d; |