
org.refcodes.codec.impls.BaseDecodeReceiverImpl 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.impls;
import java.io.IOException;
import org.refcodes.codec.BaseCodecConfig;
import org.refcodes.codec.BaseCodecMetrics;
import org.refcodes.codec.BaseDecodeReceiver;
import org.refcodes.component.CloseException;
import org.refcodes.component.ConnectionStatus;
import org.refcodes.component.LinkComponent.LinkAutomaton;
import org.refcodes.component.OpenException;
import org.refcodes.component.impls.DeviceAutomatonImpl;
import org.refcodes.exception.ExceptionUtility;
import org.refcodes.io.ByteReceiver;
/**
* Vanilla plain implementation of the {@link BaseDecodeReceiver} interface to
* be used with {@link ByteReceiver} instances. TODO: Do error handling.
*/
public class BaseDecodeReceiverImpl implements BaseDecodeReceiver {
// /////////////////////////////////////////////////////////////////////////
// STATICS:
// /////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
// CONSTANTS:
// /////////////////////////////////////////////////////////////////////////
private static final int BYTE_MASK = 0xFF;
private static final int BITS_PER_BYTE = 8;
// /////////////////////////////////////////////////////////////////////////
// VARIABLES:
// /////////////////////////////////////////////////////////////////////////
private LinkAutomaton _deviceAutomaton = new DeviceAutomatonImpl();
private ByteReceiver _byteReceiver;
private BaseCodecMetrics _baseCodecMetrics = BaseCodecConfig.BASE64;
private int _trailingBytes = 0;
int _word = 0;
private byte[] _decodedBytes = new byte[_baseCodecMetrics.getBytesPerInt()];
private int _readIndex = 0;
// /////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS:
// /////////////////////////////////////////////////////////////////////////
public BaseDecodeReceiverImpl( ByteReceiver aByteReceiver ) {
_byteReceiver = aByteReceiver;
try {
_deviceAutomaton.open();
}
catch ( OpenException ignore ) {}
}
// /////////////////////////////////////////////////////////////////////////
// INJECTION:
// /////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
// METHODS:
// /////////////////////////////////////////////////////////////////////////
@Override
public BaseCodecMetrics getBaseCodecMetrics() {
return _baseCodecMetrics;
}
@Override
public void setBaseCodecMetrics( BaseCodecMetrics aBaseCodecMetrics ) {
_baseCodecMetrics = aBaseCodecMetrics;
_decodedBytes = new byte[_baseCodecMetrics.getBytesPerInt()];
}
@Override
public BaseDecodeReceiver withBaseCodecMetrics( BaseCodecMetrics aBaseCodecMetrics ) {
setBaseCodecMetrics( aBaseCodecMetrics );
return this;
}
@Override
public boolean hasDatagram() throws OpenException {
return _byteReceiver.hasDatagram();
}
@Override
public byte[] readDatagrams() throws OpenException, InterruptedException {
if ( _readIndex > 0 ) {
// TODO: Untested, write test code into BaseDecodeInputStreamReceiverTest!
byte[] theDecodedBytes = new byte[_decodedBytes.length - _readIndex];
int l = 0;
for ( int i = _readIndex; i < _decodedBytes.length; i++ ) {
theDecodedBytes[l++] = _decodedBytes[i];
}
_readIndex = 0;
return theDecodedBytes;
}
try {
char eRead;
for ( int l = 0; l < _baseCodecMetrics.getDigitsPerInt(); l++ ) {
_word <<= _baseCodecMetrics.getBitsPerDigit();
eRead = (char) _byteReceiver.readDatagram();
if ( eRead != _baseCodecMetrics.getPaddingChar() ) {
_word |= (int) _baseCodecMetrics.toValue( eRead ) & BYTE_MASK;
}
else {
_trailingBytes++;
}
}
for ( int i = 0; i < _baseCodecMetrics.getBytesPerInt(); i++ ) {
int theIndex = _baseCodecMetrics.getBytesPerInt() - i - 1;
_decodedBytes[theIndex] = (byte) _word;
_word >>= BITS_PER_BYTE;
}
_word = 0;
}
catch ( IOException e ) {
throw new OpenException( "Unable to read from the provided receiver <" + _byteReceiver + ">: " + ExceptionUtility.toMessage( e ), e );
}
if ( _trailingBytes != 0 ) {
int theLastBlockSize = _baseCodecMetrics.getBytesPerInt() - _trailingBytes;
byte[] theDecodedBytes = new byte[theLastBlockSize];
for ( int i = 0; i < theLastBlockSize; i++ ) {
theDecodedBytes[i] = _decodedBytes[i];
}
return theDecodedBytes;
}
return _decodedBytes;
}
@Override
public byte readDatagram() throws OpenException, InterruptedException {
// TODO: Untested, write test code into BaseDecodeInputStreamReceiverTest!
if ( _readIndex == 0 ) {
readDatagrams();
}
byte theDecodedByte = _decodedBytes[_readIndex++];
if ( _readIndex >= _decodedBytes.length ) _readIndex = 0;
return theDecodedByte;
}
@Override
public void releaseAll() {
synchronized ( this ) {
notifyAll();
}
}
@Override
public synchronized boolean isOpened() {
return _deviceAutomaton.isOpened();
}
@Override
public synchronized boolean isClosable() {
return _deviceAutomaton.isClosable();
}
@Override
public synchronized void close() throws CloseException {
try {
_byteReceiver.close();
}
catch ( IOException e ) {
throw new CloseException( "Unable to close the receiver <" + _byteReceiver + ">", e );
}
_deviceAutomaton.close();
}
@Override
public synchronized boolean isClosed() {
return _deviceAutomaton.isClosed();
}
@Override
public synchronized ConnectionStatus getConnectionStatus() {
return _deviceAutomaton.getConnectionStatus();
}
// /////////////////////////////////////////////////////////////////////////
// HOOKS:
// /////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
// HELPER:
// /////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
// INNER CLASSES:
// /////////////////////////////////////////////////////////////////////////
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy