blob: f3fc1c3e15bbbb6fffad64aef52c1520e02b4106 [file] [log] [blame]
David Reissea5e75a2008-03-07 20:12:20 +00001// Copyright (c) 2006- Facebook
2// Distributed under the Thrift Software License
3//
4// See accompanying file LICENSE or visit the Thrift site at:
5// http://developers.facebook.com/thrift/
6
7package com.facebook.thrift.protocol;
8
9/**
10 * Class for encoding and decoding Base64 data.
11 *
12 * This class is kept at package level because the interface does no input
13 * validation and is therefore too low-level for generalized reuse.
14 *
15 * Note also that the encoding does not pad with equal signs , as discussed in
16 * section 2.2 of the RFC (http://www.faqs.org/rfcs/rfc3548.html). Furthermore,
17 * bad data encountered when decoding is neither rejected or ignored but simply
18 * results in bad decoded data -- this is not in compliance with the RFC but is
19 * done in the interest of performance.
20 *
21 * @author Chad Walters <chad@powerset.com>
22 */
23class TBase64Utils {
24
25 private static final String ENCODE_TABLE =
26 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
27
28 /**
29 * Encode len bytes of data in src at offset srcOff, storing the result into
30 * dst at offset dstOff. len must be 1, 2, or 3. dst must have at least len+1
31 * bytes of space at dstOff. src and dst should not be the same object. This
32 * method does no validation of the input values in the interest of
33 * performance.
34 *
35 * @param src the source of bytes to encode
36 * @param srcOff the offset into the source to read the unencoded bytes
37 * @param len the number of bytes to encode (must be 1, 2, or 3).
38 * @param dst the destination for the encoding
39 * @param dstOff the offset into the destination to place the encoded bytes
40 */
41 static final void encode(byte[] src, int srcOff, int len, byte[] dst,
42 int dstOff) {
43 dst[dstOff] = (byte)ENCODE_TABLE.charAt((src[srcOff] >> 2) & 0x3F);
44 if (len == 3) {
45 dst[dstOff + 1] =
46 (byte)ENCODE_TABLE.charAt(
47 ((src[srcOff] << 4) + (src[srcOff+1] >> 4)) & 0x3F);
48 dst[dstOff + 2] =
49 (byte)ENCODE_TABLE.charAt(
50 ((src[srcOff+1] << 2) + (src[srcOff+2] >> 6)) & 0x3F);
51 dst[dstOff + 3] =
52 (byte)ENCODE_TABLE.charAt(src[srcOff+2] & 0x3F);
53 }
54 else if (len == 2) {
55 dst[dstOff+1] =
56 (byte)ENCODE_TABLE.charAt(
57 ((src[srcOff] << 4) + (src[srcOff+1] >> 4)) & 0x3F);
58 dst[dstOff + 2] =
59 (byte)ENCODE_TABLE.charAt((src[srcOff+1] << 2) & 0x3F);
60
61 }
62 else { // len == 1) {
63 dst[dstOff + 1] =
64 (byte)ENCODE_TABLE.charAt((src[srcOff] << 4) & 0x3F);
65 }
66 }
67
68 private static final byte[] DECODE_TABLE = {
69 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
70 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
71 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63,
72 52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1,
73 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,
74 15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,
75 -1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,
76 41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1,
77 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
78 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
79 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
80 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
81 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
82 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
83 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
84 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
85 };
86
87 /**
88 * Decode len bytes of data in src at offset srcOff, storing the result into
89 * dst at offset dstOff. len must be 2, 3, or 4. dst must have at least len-1
90 * bytes of space at dstOff. src and dst may be the same object as long as
91 * dstoff <= srcOff. This method does no validation of the input values in
92 * the interest of performance.
93 *
94 * @param src the source of bytes to decode
95 * @param srcOff the offset into the source to read the encoded bytes
96 * @param len the number of bytes to decode (must be 2, 3, or 4)
97 * @param dst the destination for the decoding
98 * @param dstOff the offset into the destination to place the decoded bytes
99 */
100 static final void decode(byte[] src, int srcOff, int len, byte[] dst,
101 int dstOff) {
102 dst[dstOff] = (byte)
103 ((DECODE_TABLE[src[srcOff] & 0x0FF] << 2) |
104 (DECODE_TABLE[src[srcOff+1] & 0x0FF] >> 4));
105 if (len > 2) {
106 dst[dstOff+1] = (byte)
107 (((DECODE_TABLE[src[srcOff+1] & 0x0FF] << 4) & 0xF0) |
108 (DECODE_TABLE[src[srcOff+2] & 0x0FF] >> 2));
109 if (len > 3) {
110 dst[dstOff+2] = (byte)
111 (((DECODE_TABLE[src[srcOff+2] & 0x0FF] << 6) & 0xC0) |
112 DECODE_TABLE[src[srcOff+3] & 0x0FF]);
113 }
114 }
115 }
116}