@CanIgnoreReturnValue
    @Override
    public boolean process(byte[] input, int offset, int len, boolean finish) {
      // Using local variables makes the encoder about 9% faster.
      final byte[] alphabet = this.alphabet;
      final byte[] output = this.output;
      int op = 0;
      int count = this.count;

      int p = offset;
      len += offset;
      int v = -1;

      // First we need to concatenate the tail of the previous call
      // with any input bytes available now and see if we can empty
      // the tail.

      switch (tailLen) {
        case 0:
          // There was no tail.
          break;

        case 1:
          if (p + 2 <= len) {
            // A 1-byte tail with at least 2 bytes of
            // input available now.
            v = ((tail[0] & 0xff) << 16) | ((input[p++] & 0xff) << 8) | (input[p++] & 0xff);
            tailLen = 0;
          }
          break;

        case 2:
          if (p + 1 <= len) {
            // A 2-byte tail with at least 1 byte of input.
            v = ((tail[0] & 0xff) << 16) | ((tail[1] & 0xff) << 8) | (input[p++] & 0xff);
            tailLen = 0;
          }
          break;
        default:
          break;
      }

      if (v != -1) {
        output[op++] = alphabet[(v >> 18) & 0x3f];
        output[op++] = alphabet[(v >> 12) & 0x3f];
        output[op++] = alphabet[(v >> 6) & 0x3f];
        output[op++] = alphabet[v & 0x3f];
        if (--count == 0) {
          if (doCr) {
            output[op++] = '\r';
          }
          output[op++] = '\n';
          count = LINE_GROUPS;
        }
      }

      // At this point either there is no tail, or there are fewer
      // than 3 bytes of input available.

      // The main loop, turning 3 input bytes into 4 output bytes on
      // each iteration.
      while (p + 3 <= len) {
        v = ((input[p] & 0xff) << 16) | ((input[p + 1] & 0xff) << 8) | (input[p + 2] & 0xff);
        output[op] = alphabet[(v >> 18) & 0x3f];
        output[op + 1] = alphabet[(v >> 12) & 0x3f];
        output[op + 2] = alphabet[(v >> 6) & 0x3f];
        output[op + 3] = alphabet[v & 0x3f];
        p += 3;
        op += 4;
        if (--count == 0) {
          if (doCr) {
            output[op++] = '\r';
          }
          output[op++] = '\n';
          count = LINE_GROUPS;
        }
      }

      if (finish) {
        // Finish up the tail of the input.  Note that we need to
        // consume any bytes in tail before any bytes
        // remaining in input; there should be at most two bytes
        // total.

        if (p - tailLen == len - 1) {
          int t = 0;
          v = ((tailLen > 0 ? tail[t++] : input[p++]) & 0xff) << 4;
          tailLen -= t;
          output[op++] = alphabet[(v >> 6) & 0x3f];
          output[op++] = alphabet[v & 0x3f];
          if (doPadding) {
            output[op++] = '=';
            output[op++] = '=';
          }
          if (doNewline) {
            if (doCr) {
              output[op++] = '\r';
            }
            output[op++] = '\n';
          }
        } else if (p - tailLen == len - 2) {
          int t = 0;
          v =
              (((tailLen > 1 ? tail[t++] : input[p++]) & 0xff) << 10)
                  | (((tailLen > 0 ? tail[t++] : input[p++]) & 0xff) << 2);
          tailLen -= t;
          output[op++] = alphabet[(v >> 12) & 0x3f];
          output[op++] = alphabet[(v >> 6) & 0x3f];
          output[op++] = alphabet[v & 0x3f];
          if (doPadding) {
            output[op++] = '=';
          }
          if (doNewline) {
            if (doCr) {
              output[op++] = '\r';
            }
            output[op++] = '\n';
          }
        } else if (doNewline && op > 0 && count != LINE_GROUPS) {
          if (doCr) {
            output[op++] = '\r';
          }
          output[op++] = '\n';
        }

        assert tailLen == 0;
        assert p == len;
      } else {
        // Save the leftovers in tail to be consumed on the next
        // call to encodeInternal.

        if (p == len - 1) {
          tail[tailLen++] = input[p];
        } else if (p == len - 2) {
          tail[tailLen++] = input[p];
          tail[tailLen++] = input[p + 1];
        }
      }

      this.op = op;
      this.count = count;

      return true;
    }
Processes the input to encode it in base 64.

<p>This function always returns true -- encoding can never fail. So if one knows that one has
this class one can ignore the return value.
java_src/src/main/java/com/google/crypto/tink/subtle/Base64.java