/// <exception cref="System.IO.IOException"/> protected internal virtual int _readBinary(com.fasterxml.jackson.core.Base64Variant b64variant, Sharpen.OutputStream @out, byte[] buffer) { int outputPtr = 0; int outputEnd = buffer.Length - 3; int outputCount = 0; while (true) { // first, we'll skip preceding white space, if any int ch; do { if (_inputPtr >= _inputEnd) { loadMoreGuaranteed(); } ch = (int)_inputBuffer[_inputPtr++] & unchecked((int)(0xFF)); } while (ch <= INT_SPACE); int bits = b64variant.decodeBase64Char(ch); if (bits < 0) { // reached the end, fair and square? if (ch == INT_QUOTE) { break; } bits = _decodeBase64Escape(b64variant, ch, 0); if (bits < 0) { // white space to skip continue; } } // enough room? If not, flush if (outputPtr > outputEnd) { outputCount += outputPtr; @out.write(buffer, 0, outputPtr); outputPtr = 0; } int decodedData = bits; // then second base64 char; can't get padding yet, nor ws if (_inputPtr >= _inputEnd) { loadMoreGuaranteed(); } ch = _inputBuffer[_inputPtr++] & unchecked((int)(0xFF)); bits = b64variant.decodeBase64Char(ch); if (bits < 0) { bits = _decodeBase64Escape(b64variant, ch, 1); } decodedData = (decodedData << 6) | bits; // third base64 char; can be padding, but not ws if (_inputPtr >= _inputEnd) { loadMoreGuaranteed(); } ch = _inputBuffer[_inputPtr++] & unchecked((int)(0xFF)); bits = b64variant.decodeBase64Char(ch); // First branch: can get padding (-> 1 byte) if (bits < 0) { if (bits != com.fasterxml.jackson.core.Base64Variant.BASE64_VALUE_PADDING) { // as per [JACKSON-631], could also just be 'missing' padding if (ch == '"' && !b64variant.usesPadding()) { decodedData >>= 4; buffer[outputPtr++] = unchecked((byte)decodedData); break; } bits = _decodeBase64Escape(b64variant, ch, 2); } if (bits == com.fasterxml.jackson.core.Base64Variant.BASE64_VALUE_PADDING) { // Ok, must get padding if (_inputPtr >= _inputEnd) { loadMoreGuaranteed(); } ch = _inputBuffer[_inputPtr++] & unchecked((int)(0xFF)); if (!b64variant.usesPaddingChar(ch)) { throw reportInvalidBase64Char(b64variant, ch, 3, "expected padding character '" + b64variant.getPaddingChar() + "'"); } // Got 12 bits, only need 8, need to shift decodedData >>= 4; buffer[outputPtr++] = unchecked((byte)decodedData); continue; } } // Nope, 2 or 3 bytes decodedData = (decodedData << 6) | bits; // fourth and last base64 char; can be padding, but not ws if (_inputPtr >= _inputEnd) { loadMoreGuaranteed(); } ch = _inputBuffer[_inputPtr++] & unchecked((int)(0xFF)); bits = b64variant.decodeBase64Char(ch); if (bits < 0) { if (bits != com.fasterxml.jackson.core.Base64Variant.BASE64_VALUE_PADDING) { // as per [JACKSON-631], could also just be 'missing' padding if (ch == '"' && !b64variant.usesPadding()) { decodedData >>= 2; buffer[outputPtr++] = unchecked((byte)(decodedData >> 8)); buffer[outputPtr++] = unchecked((byte)decodedData); break; } bits = _decodeBase64Escape(b64variant, ch, 3); } if (bits == com.fasterxml.jackson.core.Base64Variant.BASE64_VALUE_PADDING) { /* With padding we only get 2 bytes; but we have * to shift it a bit so it is identical to triplet * case with partial output. * 3 chars gives 3x6 == 18 bits, of which 2 are * dummies, need to discard: */ decodedData >>= 2; buffer[outputPtr++] = unchecked((byte)(decodedData >> 8)); buffer[outputPtr++] = unchecked((byte)decodedData); continue; } } // otherwise, our triplet is now complete decodedData = (decodedData << 6) | bits; buffer[outputPtr++] = unchecked((byte)(decodedData >> 16)); buffer[outputPtr++] = unchecked((byte)(decodedData >> 8)); buffer[outputPtr++] = unchecked((byte)decodedData); } _tokenIncomplete = false; if (outputPtr > 0) { outputCount += outputPtr; @out.write(buffer, 0, outputPtr); } return outputCount; }
/* /********************************************************** /* Internal methods, binary access /********************************************************** */ /// <summary> /// Efficient handling for incremental parsing of base64-encoded /// textual content. /// </summary> /// <exception cref="System.IO.IOException"/> protected internal byte[] _decodeBase64(com.fasterxml.jackson.core.Base64Variant b64variant) { com.fasterxml.jackson.core.util.ByteArrayBuilder builder = _getByteArrayBuilder(); //main_loop: while (true) { // first, we'll skip preceding white space, if any int ch; do { if (_inputPtr >= _inputEnd) { loadMoreGuaranteed(); } ch = (int)_inputBuffer[_inputPtr++] & unchecked((int)(0xFF)); } while (ch <= INT_SPACE); int bits = b64variant.decodeBase64Char(ch); if (bits < 0) { // reached the end, fair and square? if (ch == INT_QUOTE) { return builder.toByteArray(); } bits = _decodeBase64Escape(b64variant, ch, 0); if (bits < 0) { // white space to skip continue; } } int decodedData = bits; // then second base64 char; can't get padding yet, nor ws if (_inputPtr >= _inputEnd) { loadMoreGuaranteed(); } ch = _inputBuffer[_inputPtr++] & unchecked((int)(0xFF)); bits = b64variant.decodeBase64Char(ch); if (bits < 0) { bits = _decodeBase64Escape(b64variant, ch, 1); } decodedData = (decodedData << 6) | bits; // third base64 char; can be padding, but not ws if (_inputPtr >= _inputEnd) { loadMoreGuaranteed(); } ch = _inputBuffer[_inputPtr++] & unchecked((int)(0xFF)); bits = b64variant.decodeBase64Char(ch); // First branch: can get padding (-> 1 byte) if (bits < 0) { if (bits != com.fasterxml.jackson.core.Base64Variant.BASE64_VALUE_PADDING) { // as per [JACKSON-631], could also just be 'missing' padding if (ch == '"' && !b64variant.usesPadding()) { decodedData >>= 4; builder.append(decodedData); return builder.toByteArray(); } bits = _decodeBase64Escape(b64variant, ch, 2); } if (bits == com.fasterxml.jackson.core.Base64Variant.BASE64_VALUE_PADDING) { // Ok, must get padding if (_inputPtr >= _inputEnd) { loadMoreGuaranteed(); } ch = _inputBuffer[_inputPtr++] & unchecked((int)(0xFF)); if (!b64variant.usesPaddingChar(ch)) { throw reportInvalidBase64Char(b64variant, ch, 3, "expected padding character '" + b64variant.getPaddingChar() + "'"); } // Got 12 bits, only need 8, need to shift decodedData >>= 4; builder.append(decodedData); continue; } } // Nope, 2 or 3 bytes decodedData = (decodedData << 6) | bits; // fourth and last base64 char; can be padding, but not ws if (_inputPtr >= _inputEnd) { loadMoreGuaranteed(); } ch = _inputBuffer[_inputPtr++] & unchecked((int)(0xFF)); bits = b64variant.decodeBase64Char(ch); if (bits < 0) { if (bits != com.fasterxml.jackson.core.Base64Variant.BASE64_VALUE_PADDING) { // as per [JACKSON-631], could also just be 'missing' padding if (ch == '"' && !b64variant.usesPadding()) { decodedData >>= 2; builder.appendTwoBytes(decodedData); return builder.toByteArray(); } bits = _decodeBase64Escape(b64variant, ch, 3); } if (bits == com.fasterxml.jackson.core.Base64Variant.BASE64_VALUE_PADDING) { /* With padding we only get 2 bytes; but we have * to shift it a bit so it is identical to triplet * case with partial output. * 3 chars gives 3x6 == 18 bits, of which 2 are * dummies, need to discard: */ decodedData >>= 2; builder.appendTwoBytes(decodedData); continue; } } // otherwise, our triplet is now complete decodedData = (decodedData << 6) | bits; builder.appendThreeBytes(decodedData); } }