All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.refcodes.serial.AsciizSegment Maven / Gradle / Ivy

Go to download

Artifact providing generic (byte) serialization functionality including a TTY-/COM-Port implementation of the serial framework as well as a (local) loopback port.

The newest version!
// /////////////////////////////////////////////////////////////////////////////
// REFCODES.ORG
// /////////////////////////////////////////////////////////////////////////////
// This code is copyright (c) by Siegfried Steiner, Munich, Germany, distributed
// on an "AS IS" BASIS WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, and licen-
// sed 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/TEXT-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.serial;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;

import org.refcodes.textual.CaseStyleBuilder;

/**
 * The {@link AsciizSegment} is an implementation of a {@link Segment} carrying
 * an ASCII encoded {@link String} as payload, terminated by a 0 ("zero")
 * indicating its end. A 0 terminated is called ACIIZ or CString. Termination
 * with 0 is done by the {@link AsciizSegment} and must not be handled by the
 * programmer, though it is up to the developer to make sure no 0 value is
 * contained within the provided {@link String}.
 */
public class AsciizSegment extends AbstractPayloadSegment implements EndOfStringByteAccessor {

	// /////////////////////////////////////////////////////////////////////////
	// STATICS:
	// /////////////////////////////////////////////////////////////////////////

	private static final long serialVersionUID = 1L;

	// /////////////////////////////////////////////////////////////////////////
	// VARIABLES:
	// /////////////////////////////////////////////////////////////////////////

	private byte _endOfStringByte;

	// /////////////////////////////////////////////////////////////////////////
	// CONSTRUCTORS:
	// /////////////////////////////////////////////////////////////////////////

	/**
	 * Constructs an empty {@link AsciizSegment}. The serialized content (as of
	 * {@link #toSequence()} or {@link #transmitTo(java.io.OutputStream)}) of an
	 * {@link AsciizSegment} represents an an ASCIIZ {@link String} (also known
	 * as CString).
	 */
	public AsciizSegment() {
		this( CaseStyleBuilder.asCamelCase( AsciizSegment.class.getSimpleName() ), "", TransmissionMetrics.DEFAULT_END_OF_STRING_BYTE );
	}

	/**
	 * Constructs an empty {@link AsciizSegment}. The serialized content (as of
	 * {@link #toSequence()} or {@link #transmitTo(java.io.OutputStream)}) of an
	 * {@link AsciizSegment} represents an an ASCIIZ {@link String} (also known
	 * as CString).
	 * 
	 * @param aTransmissionMetrics The {@link TransmissionMetrics} to be used
	 *        for configuring this instance.
	 */
	public AsciizSegment( TransmissionMetrics aTransmissionMetrics ) {
		this( CaseStyleBuilder.asCamelCase( AsciizSegment.class.getSimpleName() ), "", aTransmissionMetrics.getEndOfStringByte() );
	}

	/**
	 * Constructs an {@link AsciizSegment} with the given {@link String}
	 * payload. The serialized content (as of {@link #toSequence()} or
	 * {@link #transmitTo(java.io.OutputStream)}) of an {@link AsciizSegment}
	 * represents an an ASCIIZ {@link String} (also known as CString). It is in
	 * the responsibility of the programmer to make sure that the {@link String}
	 * does not contain any 0 ("zero") values as a value of 0 unintendedly
	 * terminates the resulting {@link String}.
	 * 
	 * @param aTransmissionMetrics The {@link TransmissionMetrics} to be used
	 *        for configuring this instance.
	 * @param aValue The payload to be contained by this {@link AsciizSegment}.
	 */
	public AsciizSegment( TransmissionMetrics aTransmissionMetrics, String aValue ) {
		this( CaseStyleBuilder.asCamelCase( AsciizSegment.class.getSimpleName() ), aValue, aTransmissionMetrics.getEndOfStringByte() );
	}

	/**
	 * Constructs an {@link AsciizSegment} with the given (ASCII encoded) bytes
	 * payload. The serialized content (as of {@link #toSequence()} or
	 * {@link #transmitTo(java.io.OutputStream)}) of an {@link AsciizSegment}
	 * represents an an ASCIIZ {@link String} (also known as CString). It is in
	 * the responsibility of the programmer to make sure that the bytes do not
	 * contain any 0 ("zero") values as a value of 0 unintendedly terminates the
	 * resulting {@link String}.
	 * 
	 * @param aTransmissionMetrics The {@link TransmissionMetrics} to be used
	 *        for configuring this instance.
	 * @param aValue The payload to be contained by this {@link AsciizSegment}.
	 */
	public AsciizSegment( TransmissionMetrics aTransmissionMetrics, byte[] aValue ) {
		this( CaseStyleBuilder.asCamelCase( AsciizSegment.class.getSimpleName() ), aValue, aTransmissionMetrics.getEndOfStringByte() );
	}

	/**
	 * Constructs an {@link AsciizSegment} with the given (ASCII encoded) bytes
	 * payload. The serialized content (as of {@link #toSequence()} or
	 * {@link #transmitTo(java.io.OutputStream)}) of an {@link AsciizSegment}
	 * represents an an ASCIIZ {@link String} (also known as CString). It is in
	 * the responsibility of the programmer to make sure that the bytes do not
	 * contain any 0 ("zero") values as a value of 0 unintendedly terminates the
	 * resulting {@link String}.
	 * 
	 * @param aAlias The alias which identifies the content of this segment.
	 * @param aTransmissionMetrics The {@link TransmissionMetrics} to be used
	 *        for configuring this instance.
	 * @param aValue The payload to be contained by this {@link AsciizSegment}.
	 */
	public AsciizSegment( String aAlias, TransmissionMetrics aTransmissionMetrics, byte[] aValue ) {
		this( aAlias, new String( aValue, StandardCharsets.US_ASCII ), aTransmissionMetrics.getEndOfStringByte() );
	}

	/**
	 * Constructs an {@link AsciizSegment} with the given {@link String}
	 * payload. The serialized content (as of {@link #toSequence()} or
	 * {@link #transmitTo(java.io.OutputStream)}) of an {@link AsciizSegment}
	 * represents an an ASCIIZ {@link String} (also known as CString). It is in
	 * the responsibility of the programmer to make sure that the {@link String}
	 * does not contain any 0 ("zero") values as a value of 0 unintendedly
	 * terminates the resulting {@link String}.
	 * 
	 * @param aAlias The alias which identifies the content of this segment.
	 * @param aTransmissionMetrics The {@link TransmissionMetrics} to be used
	 *        for configuring this instance.
	 * @param aValue The payload to be contained by this {@link AsciizSegment}.
	 */
	public AsciizSegment( String aAlias, TransmissionMetrics aTransmissionMetrics, String aValue ) {
		this( aAlias, aValue, aTransmissionMetrics.getEndOfStringByte() );
	}

	/**
	 * Constructs an {@link AsciizSegment} with the given {@link String}
	 * payload. The serialized content (as of {@link #toSequence()} or
	 * {@link #transmitTo(java.io.OutputStream)}) of an {@link AsciizSegment}
	 * represents an an ASCIIZ {@link String} (also known as CString). It is in
	 * the responsibility of the programmer to make sure that the {@link String}
	 * does not contain any 0 ("zero") values as a value of 0 unintendedly
	 * terminates the resulting {@link String}.
	 * 
	 * @param aValue The payload to be contained by this {@link AsciizSegment}.
	 */
	public AsciizSegment( String aValue ) {
		this( CaseStyleBuilder.asCamelCase( AsciizSegment.class.getSimpleName() ), aValue, TransmissionMetrics.DEFAULT_END_OF_STRING_BYTE );
	}

	/**
	 * Constructs an {@link AsciizSegment} with the given (ASCII encoded) bytes
	 * payload. The serialized content (as of {@link #toSequence()} or
	 * {@link #transmitTo(java.io.OutputStream)}) of an {@link AsciizSegment}
	 * represents an an ASCIIZ {@link String} (also known as CString). It is in
	 * the responsibility of the programmer to make sure that the bytes do not
	 * contain any 0 ("zero") values as a value of 0 unintendedly terminates the
	 * resulting {@link String}.
	 * 
	 * @param aValue The payload to be contained by this {@link AsciizSegment}.
	 */
	public AsciizSegment( byte[] aValue ) {
		this( CaseStyleBuilder.asCamelCase( AsciizSegment.class.getSimpleName() ), aValue, TransmissionMetrics.DEFAULT_END_OF_STRING_BYTE );
	}

	/**
	 * Constructs an {@link AsciizSegment} with the given (ASCII encoded) bytes
	 * payload. The serialized content (as of {@link #toSequence()} or
	 * {@link #transmitTo(java.io.OutputStream)}) of an {@link AsciizSegment}
	 * represents an an ASCIIZ {@link String} (also known as CString). It is in
	 * the responsibility of the programmer to make sure that the bytes do not
	 * contain any 0 ("zero") values as a value of 0 unintendedly terminates the
	 * resulting {@link String}.
	 * 
	 * @param aAlias The alias which identifies the content of this segment.
	 * @param aValue The payload to be contained by this {@link AsciizSegment}.
	 */
	public AsciizSegment( String aAlias, byte[] aValue ) {
		this( aAlias, new String( aValue, StandardCharsets.US_ASCII ), TransmissionMetrics.DEFAULT_END_OF_STRING_BYTE );
	}

	/**
	 * Constructs an {@link AsciizSegment} with the given {@link String}
	 * payload. The serialized content (as of {@link #toSequence()} or
	 * {@link #transmitTo(java.io.OutputStream)}) of an {@link AsciizSegment}
	 * represents an an ASCIIZ {@link String} (also known as CString). It is in
	 * the responsibility of the programmer to make sure that the {@link String}
	 * does not contain any 0 ("zero") values as a value of 0 unintendedly
	 * terminates the resulting {@link String}.
	 * 
	 * @param aAlias The alias which identifies the content of this segment.
	 * @param aValue The payload to be contained by this {@link AsciizSegment}.
	 */
	public AsciizSegment( String aAlias, String aValue ) {
		this( aAlias, aValue, TransmissionMetrics.DEFAULT_END_OF_STRING_BYTE );
	}

	/**
	 * Constructs an empty {@link AsciizSegment}. The serialized content (as of
	 * {@link #toSequence()} or {@link #transmitTo(java.io.OutputStream)}) of an
	 * {@link AsciizSegment} represents an an ASCIIZ {@link String} (also known
	 * as CString).
	 * 
	 * @param aEndOfStringByte The alternate value instead of 0 "zero"
	 *        identifying the end of the string.
	 */
	public AsciizSegment( byte aEndOfStringByte ) {
		this( CaseStyleBuilder.asCamelCase( AsciizSegment.class.getSimpleName() ), "", aEndOfStringByte );
	}

	/**
	 * Constructs an {@link AsciizSegment} with the given {@link String}
	 * payload. The serialized content (as of {@link #toSequence()} or
	 * {@link #transmitTo(java.io.OutputStream)}) of an {@link AsciizSegment}
	 * represents an an ASCIIZ {@link String} (also known as CString). It is in
	 * the responsibility of the programmer to make sure that the {@link String}
	 * does not contain any 0 ("zero") values as a value of 0 unintendedly
	 * terminates the resulting {@link String}.
	 * 
	 * @param aValue The payload to be contained by this {@link AsciizSegment}.
	 * @param aEndOfStringByte The alternate value instead of 0 "zero"
	 *        identifying the end of the string.
	 */
	public AsciizSegment( String aValue, byte aEndOfStringByte ) {
		this( CaseStyleBuilder.asCamelCase( AsciizSegment.class.getSimpleName() ), aValue, aEndOfStringByte );
	}

	/**
	 * Constructs an {@link AsciizSegment} with the given (ASCII encoded) bytes
	 * payload. The serialized content (as of {@link #toSequence()} or
	 * {@link #transmitTo(java.io.OutputStream)}) of an {@link AsciizSegment}
	 * represents an an ASCIIZ {@link String} (also known as CString). It is in
	 * the responsibility of the programmer to make sure that the bytes do not
	 * contain any 0 ("zero") values as a value of 0 unintendedly terminates the
	 * resulting {@link String}.
	 * 
	 * @param aValue The payload to be contained by this {@link AsciizSegment}.
	 * @param aEndOfStringByte The alternate value instead of 0 "zero"
	 *        identifying the end of the string.
	 */
	public AsciizSegment( byte[] aValue, byte aEndOfStringByte ) {
		this( CaseStyleBuilder.asCamelCase( AsciizSegment.class.getSimpleName() ), aValue, aEndOfStringByte );
	}

	/**
	 * Constructs an {@link AsciizSegment} with the given (ASCII encoded) bytes
	 * payload. The serialized content (as of {@link #toSequence()} or
	 * {@link #transmitTo(java.io.OutputStream)}) of an {@link AsciizSegment}
	 * represents an an ASCIIZ {@link String} (also known as CString). It is in
	 * the responsibility of the programmer to make sure that the bytes do not
	 * contain any 0 ("zero") values as a value of 0 unintendedly terminates the
	 * resulting {@link String}.
	 * 
	 * @param aAlias The alias which identifies the content of this segment.
	 * @param aValue The payload to be contained by this {@link AsciizSegment}.
	 * @param aEndOfStringByte The alternate value instead of 0 "zero"
	 *        identifying the end of the string.
	 */
	public AsciizSegment( String aAlias, byte[] aValue, byte aEndOfStringByte ) {
		this( aAlias, new String( aValue, StandardCharsets.US_ASCII ), aEndOfStringByte );
	}

	/**
	 * Constructs an {@link AsciizSegment} with the given {@link String}
	 * payload. The serialized content (as of {@link #toSequence()} or
	 * {@link #transmitTo(java.io.OutputStream)}) of an {@link AsciizSegment}
	 * represents an an ASCIIZ {@link String} (also known as CString). It is in
	 * the responsibility of the programmer to make sure that the {@link String}
	 * does not contain any 0 ("zero") values as a value of 0 unintendedly
	 * terminates the resulting {@link String}.
	 * 
	 * @param aAlias The alias which identifies the content of this segment.
	 * @param aValue The payload to be contained by this {@link AsciizSegment}.
	 * @param aEndOfStringByte The alternate value instead of 0 "zero"
	 *        identifying the end of the string.
	 */
	public AsciizSegment( String aAlias, String aValue, byte aEndOfStringByte ) {
		super( aAlias, aValue );
		_endOfStringByte = aEndOfStringByte;
	}

	// /////////////////////////////////////////////////////////////////////////
	// METHODS:
	// /////////////////////////////////////////////////////////////////////////

	/**
	 * {@inheritDoc}
	 */
	@Override
	public Sequence toSequence() {
		if ( getPayload() != null ) {
			return new ByteArraySequence( getPayload().getBytes( StandardCharsets.US_ASCII ) ).withAppend( _endOfStringByte );
		}
		return new ByteArraySequence( _endOfStringByte );
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public int fromTransmission( Sequence aSequence, int aOffset ) throws TransmissionException {
		for ( int i = 0; i < aSequence.getLength() - aOffset; i++ ) {
			if ( aSequence.getByteAt( aOffset + i ) == _endOfStringByte ) {
				super.setPayload( new String( aSequence.toBytes( aOffset, i ), StandardCharsets.US_ASCII ) );
				return aOffset + i + 1;
			}
		}
		throw new TransmissionSequenceException( aSequence, "No terminating <" + _endOfStringByte + "> found in the given sequence starting at offset <" + aOffset + ">." );
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void receiveFrom( InputStream aInputStream, OutputStream aReturnStream ) throws IOException {
		byte eByte;
		final ByteArraySequence theSequence = new ByteArraySequence();
		while ( ( eByte = (byte) aInputStream.read() ) != _endOfStringByte ) {
			theSequence.append( eByte );
		}
		setPayload( new String( theSequence.toBytes(), StandardCharsets.US_ASCII ) );
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public int getLength() {
		return getPayload() != null ? toSequence().getLength() : 0;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public SerialSchema toSchema() {
		return new SerialSchema( getAlias(), getClass(), toSequence(), getLength(), getPayload(), "A segment containing a <" + _endOfStringByte + "> terminated string payload." );
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public AsciizSegment withPayload( String aValue ) {
		setPayload( aValue );
		return this;
	}

	/**
	 * Sets the given (ASCII encoded) bytes payload.
	 * 
	 * @param aValue The payload to set.
	 */
	public void setPayload( byte[] aValue ) {
		setPayload( new String( aValue, StandardCharsets.US_ASCII ) );
	}

	/**
	 * Sets the given (ASCII encoded) bytes payload.
	 * 
	 * @param aValue The payload to set.
	 * 
	 * @return THis instance as of the builder pattern.
	 */
	public AsciizSegment withPayload( byte[] aValue ) {
		setPayload( aValue );
		return this;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public byte getEndOfStringByte() {
		return _endOfStringByte;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy