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

io.pkts.buffer.BaseBuffer Maven / Gradle / Ivy

There is a newer version: 3.0.10
Show newest version
package io.pkts.buffer;

import java.io.IOException;

/**
 * Abstract abstract buffer :-)
 *
 * @author [email protected]
 */
public abstract class BaseBuffer implements Buffer {
    protected static final byte LF = '\n';
    protected static final byte CR = '\r';

    @Override
    public abstract Buffer clone();

    @Override
    public boolean hasWritableBytes() {
        return getWritableBytes() > 0;
    }

    /**
     * Check whether we have enough space for writing the desired length.
     *
     * @param length
     * @return
     */
    protected boolean checkWritableBytesSafe(final int length) {
        return getWritableBytes() >= length;
    }

    /**
     * Convenience method for checking if we have enough readable bytes
     *
     * @param length
     *            the length the user wishes to read
     * @throws IndexOutOfBoundsException
     *             in case we don't have the bytes available
     */
    protected void checkReadableBytes(final int length) throws IndexOutOfBoundsException {
        if (!checkReadableBytesSafe(length)) {
            throw new IndexOutOfBoundsException("Not enough readable bytes");
        }
    }

    /**
     * Convenience method for checking if we have enough readable bytes
     *
     * @param length
     *            the length the user wishes to read
     * @return true if we have enough bytes available for read
     */
    protected boolean checkReadableBytesSafe(final int length) {
        return getReadableBytes() >= length;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final Buffer readUntil(final byte b) throws IOException, ByteNotFoundException {
        return readUntil(4096, b);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final Buffer readUntil(final int maxBytes, final byte... bytes) throws IOException, ByteNotFoundException,
            IllegalArgumentException {
        final Buffer result = readUntilSafe(maxBytes, bytes);
        if (result == null) {
            throw new ByteNotFoundException(bytes);
        }

        return result;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final Buffer readUntilSafe(final int maxBytes, final byte... bytes) throws IOException, IllegalArgumentException {
        final int index = indexOf(maxBytes, bytes);
        if (index == -1) {
            return null;
        }

        final int size = index - getReaderIndex();
        final Buffer result;
        if (size == 0) {
            result = Buffers.EMPTY_BUFFER;
        } else {
            result = readBytes(size);
        }

        readByte(); // consume the one at the index as well
        return result;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final int indexOf(final int maxBytes, final byte... bytes) throws IOException, ByteNotFoundException,
            IllegalArgumentException {
        if (bytes.length == 0) {
            throw new IllegalArgumentException("No bytes specified. Not sure what you want me to look for");
        }

        final int start = getReaderIndex();
        int index = -1;

        while (hasReadableBytes() && getReaderIndex() - start < maxBytes && index == -1) {
            if (isByteInArray(readByte(), bytes)) {
                index = getReaderIndex() - 1;
            }
        }

        setReaderIndex(start);

        if (getReaderIndex() - start >= maxBytes) {
            throw new ByteNotFoundException(maxBytes, bytes);
        }

        return index;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final int indexOf(final byte b) throws IOException, ByteNotFoundException, IllegalArgumentException {
        return this.indexOf(4096, b);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final Buffer readLine() throws IOException {
        final int start = getReaderIndex();
        boolean foundCR = false;
        while (hasReadableBytes()) {
            final byte b = readByte();
            switch (b) {
                case LF:
                    return slice(start, getReaderIndex() - (foundCR ? 2 : 1));
                case CR:
                    foundCR = true;
                    break;
                default:
                    if (foundCR) {
                        setReaderIndex(getReaderIndex() - 1);
                        // return slice(start, this.lowerBoundary + this.readerIndex - 1);
                        return slice(start, getReaderIndex() - 1);
                    }
            }
        }

        // i guess there were nothing for us to read
        if (start >= getReaderIndex()) {
            return null;
        }

        return slice(start, getReaderIndex());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final Buffer readUntilSingleCRLF() throws IOException {
        final int start = getReaderIndex();
        int found = 0;
        while (found < 2 && hasReadableBytes()) {
            final byte b = readByte();
            if (found == 0 && b == CR) {
                ++found;
            } else if (found == 1 && b == LF) {
                ++found;
            } else {
                found = 0;
            }
        }
        if (found == 2) {
            return slice(start, getReaderIndex() - 2);
        } else {
            setReaderIndex(start);
            return null;
        }
    }

    @Override
    public final Buffer readUntilDoubleCRLF() throws IOException {
        final int start = getReaderIndex();
        int found = 0;
        while (found < 4 && hasReadableBytes()) {
            final byte b = readByte();
            if ((found == 0 || found == 2) && b == CR) {
                ++found;
            } else if ((found == 1 || found == 3) && b == LF) {
                ++found;
            } else {
                found = 0;
            }
        }
        if (found == 4) {
            return slice(start, getReaderIndex() - 4);
        } else {
            setReaderIndex(start);
            return null;
        }
    }

    @Override
    public final int parseToInt() throws NumberFormatException, IOException {
        return parseToInt(10);
    }

    /**
     * (Copied from the Integer class and slightly altered to read from this
     * buffer instead of a String)
     *
     * Parses the string argument as a signed integer in the radix specified by
     * the second argument. The characters in the string must all be digits of
     * the specified radix (as determined by whether
     * {@link java.lang.Character#digit(char, int)} returns a nonnegative
     * value), except that the first character may be an ASCII minus sign
     * '-' ('\u002D') to indicate a negative
     * value. The resulting integer value is returned.
     * 

* An exception of type NumberFormatException is thrown if any * of the following situations occurs: *

    *
  • The first argument is null or is a string of length * zero. *
  • The radix is either smaller than * {@link java.lang.Character#MIN_RADIX} or larger than * {@link java.lang.Character#MAX_RADIX}. *
  • Any character of the string is not a digit of the specified radix, * except that the first character may be a minus sign '-' ( * '\u002D') provided that the string is longer than length * 1. *
  • The value represented by the string is not a value of type * int. *
*

* Examples:

* *
     * parseInt("0", 10) returns 0
     * parseInt("473", 10) returns 473
     * parseInt("-0", 10) returns 0
     * parseInt("-FF", 16) returns -255
     * parseInt("1100110", 2) returns 102
     * parseInt("2147483647", 10) returns 2147483647
     * parseInt("-2147483648", 10) returns -2147483648
     * parseInt("2147483648", 10) throws a NumberFormatException
     * parseInt("99", 8) throws a NumberFormatException
     * parseInt("Kona", 10) throws a NumberFormatException
     * parseInt("Kona", 27) returns 411787
     * 
* *
* * @param radix * the radix to be used while parsing s. * @return the integer represented by the string argument in the specified * radix. * @exception NumberFormatException * if the String does not contain a parsable * int. */ @Override public final int parseToInt(final int radix) throws NumberFormatException, IOException { if (getReadableBytes() == 0) { throw new NumberFormatException("Buffer is empty, cannot convert it to an integer"); } if (radix < Character.MIN_RADIX) { throw new NumberFormatException("radix " + radix + " less than Character.MIN_RADIX"); } if (radix > Character.MAX_RADIX) { throw new NumberFormatException("radix " + radix + " greater than Character.MAX_RADIX"); } int result = 0; boolean negative = false; int i = getReaderIndex(); final int max = getReadableBytes() + getReaderIndex(); final int limit; final int multmin; int digit; if (max > 0) { if (getByte(i) == (byte) '-') { negative = true; limit = Integer.MIN_VALUE; i++; } else { limit = -Integer.MAX_VALUE; } multmin = limit / radix; if (i < max) { digit = Character.digit((char) getByte(i++), radix); if (digit < 0) { throw new NumberFormatException("For input string: \"" + this + "\""); } else { result = -digit; } } while (i < max) { // Accumulating negatively avoids surprises near MAX_VALUE digit = Character.digit((char) getByte(i++), radix); if (digit < 0) { throw new NumberFormatException("For input string: \"" + this + "\""); } if (result < multmin) { throw new NumberFormatException("For input string: \"" + this + "\""); } result *= radix; if (result < limit + digit) { throw new NumberFormatException("For input string: \"" + this + "\""); } result -= digit; } } else { throw new NumberFormatException("For input string: \"" + this + "\""); } if (negative) { if (i > 1) { return result; } else { /* Only got "-" */ throw new NumberFormatException("For input string: \"" + this + "\""); } } else { return -result; } } protected static boolean isByteInArray(final byte b, final byte[] bytes) { for (final byte x : bytes) { if (x == b) { return true; } } return false; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy