/* ==================================================================== | |
* Copyright (c) 2006 J.T. Beetstra | |
* | |
* Permission is hereby granted, free of charge, to any person obtaining | |
* a copy of this software and associated documentation files (the | |
* "Software"), to deal in the Software without restriction, including | |
* without limitation the rights to use, copy, modify, merge, publish, | |
* distribute, sublicense, and/or sell copies of the Software, and to | |
* permit persons to whom the Software is furnished to do so, subject to | |
* the following conditions: | |
* | |
* The above copyright notice and this permission notice shall be | |
* included in all copies or substantial portions of the Software. | |
* | |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | |
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
* ==================================================================== | |
*/ | |
package com.beetstra.jutf7; | |
import java.util.Arrays; | |
/** | |
* <p> | |
* Represent a base 64 mapping. The 64 characters used in the encoding can be | |
* specified, since modified-UTF-7 uses other characters than UTF-7 (',' instead | |
* of '/'). | |
* </p> | |
* <p> | |
* The exact type of the arguments and result values is adapted to the needs of | |
* the encoder and decoder, as opposed to following a strict interpretation of | |
* base 64. | |
* </p> | |
* <p> | |
* Base 64, as specified in RFC 2045, is an encoding used to encode bytes as | |
* characters. In (modified-)UTF-7 however, it is used to encode characters as | |
* bytes, using some intermediate steps: | |
* </p> | |
* <ol> | |
* <li>Encode all characters as a 16-bit (UTF-16) integer value</li> | |
* <li>Write this as stream of bytes (most-significant first)</li> | |
* <li>Encode these bytes using (modified) base 64 encoding</li> | |
* <li>Write the thus formed stream of characters as a stream of bytes, using | |
* ASCII encoding</li> | |
* </ol> | |
* | |
* @author Jaap Beetstra | |
*/ | |
class Base64Util { | |
private static final int ALPHABET_LENGTH = 64; | |
private final char[] alphabet; | |
private final int[] inverseAlphabet; | |
/** | |
* Initializes the class with the specified encoding/decoding alphabet. | |
* | |
* @param alphabet | |
* @throws IllegalArgumentException if alphabet is not 64 characters long or | |
* contains characters which are not 7-bit ASCII | |
*/ | |
Base64Util(final String alphabet) { | |
this.alphabet = alphabet.toCharArray(); | |
if (alphabet.length() != ALPHABET_LENGTH) | |
throw new IllegalArgumentException("alphabet has incorrect length (should be 64, not " | |
+ alphabet.length() + ")"); | |
inverseAlphabet = new int[128]; | |
Arrays.fill(inverseAlphabet, -1); | |
for (int i = 0; i < this.alphabet.length; i++) { | |
final char ch = this.alphabet[i]; | |
if (ch >= 128) | |
throw new IllegalArgumentException("invalid character in alphabet: " + ch); | |
inverseAlphabet[ch] = i; | |
} | |
} | |
/** | |
* Returns the integer value of the six bits represented by the specified | |
* character. | |
* | |
* @param ch The character, as a ASCII encoded byte | |
* @return The six bits, as an integer value, or -1 if the byte is not in | |
* the alphabet | |
*/ | |
int getSextet(final byte ch) { | |
if (ch >= 128) | |
return -1; | |
return inverseAlphabet[ch]; | |
} | |
/** | |
* Tells whether the alphabet contains the specified character. | |
* | |
* @param ch The character | |
* @return true if the alphabet contains <code>ch</code>, false otherwise | |
*/ | |
boolean contains(final char ch) { | |
if (ch >= 128) | |
return false; | |
return inverseAlphabet[ch] >= 0; | |
} | |
/** | |
* Encodes the six bit group as a character. | |
* | |
* @param sextet The six bit group to be encoded | |
* @return The ASCII value of the character | |
*/ | |
byte getChar(final int sextet) { | |
return (byte)alphabet[sextet]; | |
} | |
} |