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

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

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

import java.io.IOException;

import static com.ionos.network.commons.address.BitsAndBytes.BYTE_MASK;
import static com.ionos.network.commons.address.BitsAndBytes.appendHex;

/**
 * Text formatting alternatives for IP address in multiple notations.
 * @see IP
 * @see AddressFormat
 * @author Stephan Fuhrmann
 **/
public final class IPFormats {

    /** No instance allowed. */
    private IPFormats() {
        // no instance allowed
    }

    /** IP formatter in dotted decimal notation, like {@code 172.20.0.11}.
     * @see 
     *     Dot-decimal notation
     * */
    public static final AddressFormat DOTTED_DECIMAL =
            new AbstractAddressFormat() {
                @Override
                public  A format(
                        final IPv4 ip,
                        final A toAppendTo)
                        throws IOException {
                    final byte[] address = ip.address;
                    // decimals with dot separators
                    for (int i = 0; i < address.length; i++) {
                        if (i > 0) {
                            toAppendTo.append('.');
                        }
                        toAppendTo.append(Integer.toString(
                                BYTE_MASK & address[i]));
                    }
                    return toAppendTo;
                }
    };

    /** IP formatter in uncompressed colon-separated notation, like
     * {@code 0:ffff:1111:5555:f:44:aa:0}.
     * @see 
     *     IPv6 address
     * */
    public static final AddressFormat
            COLON_SEPARATED_HEXTETS =
            new AbstractAddressFormat() {
                @Override
                public  A format(
                        final IPv6 ip,
                        final A toAppendTo)
                        throws IOException {
                    final byte[] address = ip.address;
                    // everything else goes HEX with word components
                    for (int i = 0; i < address.length; i += 2) {
                        if (i > 0) {
                            toAppendTo.append(':');
                        }
                        appendHex(toAppendTo, address[i], address[i + 1]);
                    }
                    return toAppendTo;
                }
    };

    /** IP formatter in leading-zero uncompressed colon-separated
     * notation,
     * like {@code 0000:ffff:1111:5555:000f:0044:00aa:0000}.
     * This IP address format has a fixed character size.
     * @see 
     *     IPv6 address
     * */
    public static final AddressFormat
            COLON_SEPARATED_ZEROED_HEXTETS =
            new HexadecimalAddressFormat<>(':', 4);

    /** Canonical IPv6 formatter. This is the compressed
     * colon-separated notation in lower case.
     * Example: {@code ::ffff:1111:5555:f:44:aa:0}.
     * @see 
     *     A Recommendation for IPv6 Address Text
     *     Representation
     * */
    public static final AddressFormat
            RFC_5952 =
            new AbstractAddressFormat() {
                @Override
                public  A format(
                        final IPv6 ip,
                        final A toAppendTo)
                        throws IOException {
                    final byte[] address = ip.address;

                    final int[] offsetLength =
                            findCompressionOffsetAndLength(address);

                    // offset of longest 0-run
                    int maxOfs = offsetLength[0];
                    // length of longest 0-run
                    int maxLen = offsetLength[1];

                    if (maxLen <= 2) {
                        return COLON_SEPARATED_HEXTETS
                                .format(ip, toAppendTo);
                    }
                    // left part
                    for (int i = 0; i < maxOfs; i += 2) {
                        if (i > 0) {
                            toAppendTo.append(':');
                        }
                        appendHex(toAppendTo, address[i], address[i + 1]);
                    }
                    toAppendTo.append(':');

                    // right part
                    for (int i = maxOfs + maxLen; i < address.length; i += 2) {
                        toAppendTo.append(':');
                        appendHex(toAppendTo, address[i], address[i + 1]);
                    }
                    if (maxOfs + maxLen == address.length) {
                        toAppendTo.append(':');
                    }
                    return toAppendTo;
                }
            };

    /** Maximum digits of a decimal byte. */
    private static final int MAX_DIGITS_DEC_BYTE = 3;

    /** IP formatter in system id notation as used in IS-IS, like
     * {@code 00 10 01 00 10 01}.
     * */
    public static final AddressFormat SYSTEM_ID_NOTATION =
            new AbstractAddressFormat() {
                    @Override
                    public  A format(
                            final IPv4 ip,
                            final A toAppendTo)
                            throws IOException {
                        final byte[] address = ip.address;
                        int count = 0;

                        for (byte b : address) {
                            String str = Integer.toString(b & BYTE_MASK);
                            for (int i = str.length();
                                 i < MAX_DIGITS_DEC_BYTE;
                                 i++) {
                                if (count > 0 && count % 2 == 0) {
                                    toAppendTo.append(' ');
                                }
                                count++;
                                toAppendTo.append('0');
                            }
                            for (char c : str.toCharArray()) {
                                if (count > 0 && count % 2 == 0) {
                                    toAppendTo.append(' ');
                                }
                                count++;
                                toAppendTo.append(c);
                            }
                        }
                        return toAppendTo;
                    }
            };

    /** Find the maximum run of zero bytes in the address.
     * @param address the address to find the maximum sequence in.
     * @return a two-element array of offset and length in bytes. Can both be
     * {@code -1} if no zero bnytes are found.
     * */
    private static int[] findCompressionOffsetAndLength(final byte[] address) {
        // offset of longest 0-run
        int maxOfs = -1;
        // length of longest 0-run
        int maxLen = -1;
        for (int i = 0; i < address.length; i += 2) {
            int curLen = 0;
            for (int j = 0; i + j < address.length; j += 2) {
                if (address[i + j] == 0
                        && address[i + j + 1] == 0) {
                    curLen += 2;
                } else {
                    break;
                }
            }

            if (curLen > maxLen) {
                maxOfs = i;
                maxLen = curLen;
            }
        }
        return new int[] {maxOfs, maxLen};
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy