org.refcodes.codec.BaseMetricsImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of refcodes-codec Show documentation
Show all versions of refcodes-codec Show documentation
Artifact with encoding and decoding (not in terms of encryption/decryption)
implementations (codecs) such as BASE64 encoding / decoding.
// /////////////////////////////////////////////////////////////////////////////
// REFCODES.ORG
// /////////////////////////////////////////////////////////////////////////////
// This code is copyright (c) by Siegfried Steiner, Munich, Germany and licensed
// under the following (see "http://en.wikipedia.org/wiki/Multi-licensing")
// licenses:
// -----------------------------------------------------------------------------
// GNU General Public License, v3.0 ("http://www.gnu.org/licenses/gpl-3.0.html")
// -----------------------------------------------------------------------------
// Apache License, v2.0 ("http://www.apache.org/licenses/LICENSE-2.0")
// -----------------------------------------------------------------------------
// Please contact the copyright holding author(s) of the software artifacts in
// question for licensing issues not being covered by the above listed licenses,
// also regarding commercial licensing models or regarding the compatibility
// with other open source licenses.
// /////////////////////////////////////////////////////////////////////////////
package org.refcodes.codec;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.refcodes.data.CharSet;
import org.refcodes.data.Padding;
import org.refcodes.exception.BugException;
/**
* {@link BaseMetrics} implementation for playing around with your own
* configuration. You may use a template as one provided by {@link BaseConfig}
* and tweak some attributes as you wish.
*/
public class BaseMetricsImpl implements BaseMetrics {
// /////////////////////////////////////////////////////////////////////////
// STATICS:
// /////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
// CONSTANTS:
// /////////////////////////////////////////////////////////////////////////
private static final int BYTES_PER_INT = 4;
private static final int BITS_PER_BYTE = 8;
// /////////////////////////////////////////////////////////////////////////
// VARIABLES:
// /////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
// VARIABLES:
// /////////////////////////////////////////////////////////////////////////
private Map _charToValueMap = new HashMap<>();
private int _numberBase;
private int _bytesPerInt;
private char[] _charSet;
private int _bitsPerDigit;
private int _digitsPerInt;
private int _digitsPerByte;
private int _digitMask;
private char _paddingChar;
// /////////////////////////////////////////////////////////////////////////
// CONSTRUCTOR:
// /////////////////////////////////////////////////////////////////////////
/**
* Instantiates a new base metrics impl.
*
* @param aBase the base
*/
public BaseMetricsImpl( int aBase ) {
this( aBase, CharSet.BASE64.getCharSet() );
}
/**
* Instantiates a new base metrics impl.
*
* @param aBase the base
* @param aCharSet the char set
*/
public BaseMetricsImpl( int aBase, char[] aCharSet ) {
this( aBase, aCharSet, Padding.BASE64.getChar() );
}
/**
* Instantiates a new base metrics impl.
*
* @param aBase the base
* @param aCharSet the char set
* @param aPaddingChar the padding char
*/
public BaseMetricsImpl( int aBase, char[] aCharSet, char aPaddingChar ) {
_numberBase = aBase;
_charSet = aCharSet;
_bitsPerDigit = toBitsPerDigit( aBase );
_digitMask = toDigitMask( _bitsPerDigit );
_bytesPerInt = toBytesPerInt( _bitsPerDigit );
_digitsPerInt = toDigitsPerInt( _bytesPerInt, _bitsPerDigit );
_digitsPerByte = toDigitsPerByte( aBase );
_paddingChar = aPaddingChar;
intiCharToValueMap( aCharSet );
}
/**
* Instantiates a new base metrics impl.
*
* @param aBase the base
* @param aBitsPerDigit the bits per digit
* @param aDigitsPerByte the digits per byte
* @param aDigitsPerInt the digits per int
* @param aBytesPerInt the bytes per int
* @param aCharSet the char set
*/
public BaseMetricsImpl( int aBase, int aBitsPerDigit, int aDigitsPerByte, int aDigitsPerInt, int aBytesPerInt, char[] aCharSet ) {
this( aBase, aBitsPerDigit, aDigitsPerByte, aDigitsPerInt, aBytesPerInt, aCharSet, Padding.BASE64.getChar() );
}
/**
* Instantiates a new base metrics impl.
*
* @param aBase the base
* @param aBitsPerDigit the bits per digit
* @param aDigitsPerByte the digits per byte
* @param aDigitsPerInt the digits per int
* @param aBytesPerInt the bytes per int
* @param aCharSet the char set
* @param aPaddingChar the padding char
*/
public BaseMetricsImpl( int aBase, int aBitsPerDigit, int aDigitsPerByte, int aDigitsPerInt, int aBytesPerInt, char[] aCharSet, char aPaddingChar ) {
_numberBase = aBase;
_charSet = aCharSet;
_digitMask = (int) Math.pow( 2, aBitsPerDigit ) - 1;
_bytesPerInt = aBytesPerInt;
_bitsPerDigit = aBitsPerDigit;
_digitsPerInt = aDigitsPerInt;
_digitsPerByte = aDigitsPerByte;
intiCharToValueMap( aCharSet );
_paddingChar = aPaddingChar;
}
/**
* Instantiates a new base metrics impl.
*
* @param aBaseMetrics the base metrics
*/
public BaseMetricsImpl( BaseMetrics aBaseMetrics ) {
_bitsPerDigit = aBaseMetrics.getBitsPerDigit();
_bytesPerInt = aBaseMetrics.getBytesPerInt();
intiCharToValueMap( aBaseMetrics.getCharSet() );
_digitMask = aBaseMetrics.getDigitMask();
_digitsPerByte = aBaseMetrics.getDigitsPerByte();
_digitsPerInt = aBaseMetrics.getDigitsPerInt();
_numberBase = aBaseMetrics.getNumberBase();
_paddingChar = aBaseMetrics.getPaddingChar();
}
/**
* Inti char to value map.
*
* @param aCharSet the char set
*/
private void intiCharToValueMap( char[] aCharSet ) {
for ( int i = 0; i < aCharSet.length; i++ ) {
_charToValueMap.put( aCharSet[i], i );
}
}
// /////////////////////////////////////////////////////////////////////////
// METHODS:
// /////////////////////////////////////////////////////////////////////////
/**
* {@inheritDoc}
*/
@Override
public int getNumberBase() {
return _numberBase;
}
/**
* {@inheritDoc}
*/
@Override
public char[] getCharSet() {
return _charSet;
}
/**
* {@inheritDoc}
*/
@Override
public int getBytesPerInt() {
return _bytesPerInt;
}
/**
* {@inheritDoc}
*/
@Override
public int getDigitsPerInt() {
return _digitsPerInt;
}
/**
* {@inheritDoc}
*/
@Override
public int getBitsPerDigit() {
return _bitsPerDigit;
}
/**
* {@inheritDoc}
*/
@Override
public int getDigitsPerByte() {
return _digitsPerByte;
}
/**
* {@inheritDoc}
*/
@Override
public int getDigitMask() {
return _digitMask;
}
/**
* {@inheritDoc}
*/
@Override
public int toValue( char aChar ) {
if ( aChar == _paddingChar ) return 0;
return _charToValueMap.get( aChar );
}
/**
* {@inheritDoc}
*/
@Override
public char toChar( int aValue ) {
return _charSet[aValue];
}
/**
* {@inheritDoc}
*/
@Override
public char getPaddingChar() {
return _paddingChar;
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return getClass().getSimpleName() + "(base := " + _numberBase + ", digits/int := " + _digitsPerInt + ", bytes/int := " + _bytesPerInt + ", bits/digit := " + _bitsPerDigit + ")@" + hashCode();
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + _bytesPerInt;
result = prime * result + Arrays.hashCode( _charSet );
result = prime * result + _digitMask;
result = prime * result + _digitsPerByte;
result = prime * result + _numberBase;
return result;
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals( Object obj ) {
if ( this == obj ) return true;
if ( obj == null ) return false;
if ( getClass() != obj.getClass() ) return false;
BaseMetricsImpl other = (BaseMetricsImpl) obj;
if ( _bytesPerInt != other._bytesPerInt ) return false;
if ( !Arrays.equals( _charSet, other._charSet ) ) return false;
if ( _digitMask != other._digitMask ) return false;
if ( _digitsPerByte != other._digitsPerByte ) return false;
if ( _numberBase != other._numberBase ) return false;
return true;
}
// /////////////////////////////////////////////////////////////////////////
// UTILITY:
// /////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
// HOOKS:
// /////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
// HELPER:
// /////////////////////////////////////////////////////////////////////////
/**
* To digit mask.
*
* @param aBitsPerDigit the bits per digit
* @return the int
*/
protected static int toDigitMask( int aBitsPerDigit ) {
return (int) Math.pow( 2, aBitsPerDigit ) - 1;
}
/**
* To bits per digit.
*
* @param aBase the base
* @return the int
*/
protected static int toBitsPerDigit( int aBase ) {
int theBitsPerDigit = Integer.toBinaryString( aBase - 1 ).length();
// Make it fit into byte portions of an integer:
while ( BITS_PER_BYTE % theBitsPerDigit != 0 && 2 * BITS_PER_BYTE % theBitsPerDigit != 0 && 3 * BITS_PER_BYTE % theBitsPerDigit != 0 && 4 * BITS_PER_BYTE
% theBitsPerDigit != 0 /*
* && 5 * BITS_PER_BYTE %
* theBitsPerDigit != 0
*/ ) {
theBitsPerDigit++;
}
return theBitsPerDigit;
}
/**
* To digits per int.
*
* @param aBytesPerInt the bytes per int
* @param aBitsPerDigit the bits per digit
* @return the int
*/
protected static int toDigitsPerInt( int aBytesPerInt, int aBitsPerDigit ) {
return BITS_PER_BYTE * aBytesPerInt / aBitsPerDigit;
}
/**
* To digits per byte.
*
* @param aBase the base
* @return the int
*/
protected static int toDigitsPerByte( int aBase ) {
int theDigitsPerByte = 0;
int eMax = 1;
while ( eMax < 255 ) {
theDigitsPerByte++;
eMax *= aBase;
}
return theDigitsPerByte;
}
/**
* To bytes per int.
*
* @param aBitsPerDigit the bits per digit
* @return the int
*/
protected static int toBytesPerInt( int aBitsPerDigit ) {
for ( int i = (BYTES_PER_INT * BITS_PER_BYTE); i > 0; i-- ) {
if ( i % aBitsPerDigit == 0 ) {
return i / BITS_PER_BYTE;
}
}
for ( int i = 1; i <= aBitsPerDigit; i++ ) {
if ( i * BITS_PER_BYTE % aBitsPerDigit == 0 ) {
return (i * BITS_PER_BYTE) / BITS_PER_BYTE;
}
}
throw new BugException( "We must have encountered a bug as we cannot determine the word length for a base codec with <" + aBitsPerDigit + "> bits per digit." );
}
// /////////////////////////////////////////////////////////////////////////
// INNER CLASSES:
// /////////////////////////////////////////////////////////////////////////
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy