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

com.ionos.network.commons.address.HexadecimalAddressParser Maven / Gradle / Ivy

There is a newer version: 0.14.0
Show newest version
package com.ionos.network.commons.address;

import java.util.Objects;
import java.util.function.Function;

/**
 * Parses an address in fixed-length hexadecimal text form.
 * The address String is separated with separator chars
 * every separator interval.
 * @param  the type of address to parse.
 * @see HexadecimalAddressFormat
 * @author Stephan Fuhrmann
 * */
public final class HexadecimalAddressParser
        implements AddressParser {

    /** The character to use as a separator. */
    private final char separator;

    /** The interval in characters for separators to occur. */
    private final int separatorInterval;

    /** The factory for creating instances of {@code T}. */
    private final Function factory;

    /** The factory for creating instances of {@code T}. */
    private final int addressLength;

    /**
     * Constructor of an instance.
     * @param inSeparator the character to separate the parts with.
     *                    Example: {@code ':'}
     *                    is the separator for MAC addresses.
     * @param inSeparatorInterval the number of hex digits that form the parts.
     *                            Example:
     *                            {@code 2} is the interval for fixed-length MAC
     *                            addresses if you look
     *                            at {@code ab:cd:ef:12:34:45}.
     * @param inFactory a factory to create a new instance of {@code T}
     *                  from a parsed byte array.
     *                  Example: {@code MAC::new}.
     * @param inAddressLength the length of an address array in bytes.
     * @throws NullPointerException if {@code inFactory} is {@code null}.
     * @throws IllegalArgumentException if {@code inSeparatorInterval}
     * is smaller or equal 0.
     */
    public HexadecimalAddressParser(final char inSeparator,
                                    final int inSeparatorInterval,
                                    final Function inFactory,
                                    final int inAddressLength) {
        this.separator = inSeparator;
        if (inSeparatorInterval <= 0) {
            throw new IllegalArgumentException(
                    "separatorInterval must be > 0");
        }
        this.separatorInterval = inSeparatorInterval;
        this.factory = Objects.requireNonNull(inFactory, "factory is null");
        this.addressLength = inAddressLength;
    }

    @Override
    public T parse(final String address) {
        return factory.apply(parseAsBytes(address));
    }

    @Override
    public byte[] parseAsBytes(final String address) {
        byte[] result = new byte[addressLength];
        int expectLength = addressLength * 2
                + (2 * addressLength - 1) / separatorInterval;
        if (address.length() != expectLength) {
            throw new IllegalArgumentException("Illegal address "
                    + address +  " length, expected " + expectLength);
        }

        // check separators
        for (int charIndex = separatorInterval;
             charIndex < expectLength;
             charIndex += 1 + separatorInterval) {
            char curSeparator = address.charAt(charIndex);
            if (separator != curSeparator) {
                throw new IllegalArgumentException("Illegal separator '"
                        + curSeparator + "' in address " + address);
            }
        }

        // parse the bytes
        for (int byteIndex = 0; byteIndex < addressLength; byteIndex++) {
            char firstChar = address.charAt(2 * byteIndex
                    + (2 * byteIndex) / separatorInterval);
            char secondChar = address.charAt((2 * byteIndex + 1)
                    + (2 * byteIndex + 1) / separatorInterval);
            int byteValue = BitsAndBytes.toInt(firstChar)
                    << BitsAndBytes.BITS_PER_NIBBLE
                    | BitsAndBytes.toInt(secondChar);
            result[byteIndex] = (byte) byteValue;
        }

        return result;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy