ArduinoSignalRange.java

/*******************************************************************************
 * jArduino: Arduino C++ Code Generation From Java
 * Copyright 2020 Tony Washer
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/
package net.sourceforge.jarduino.message;

import net.sourceforge.jarduino.message.ArduinoParser.ArduinoParserException;

/**
 * Arduino Signal Range.
 */
public final class ArduinoSignalRange {
    /**
     * The start character.
     */
    private static final char START = '[';

    /**
     * The end character.
     */
    private static final char END = ']';

    /**
     * the maximum value of the signal.
     */
    private final Number theMaximum;

    /**
     * the minimum value of the signal.
     */
    private final Number theMinimum;

    /**
     * Constructor.
     * @param pMinimum the min value
     * @param pMaximum the max value
     */
    private ArduinoSignalRange(final Number pMinimum,
                               final Number pMaximum) {
        /* Store values */
        theMinimum = pMinimum;
        theMaximum = pMaximum;
    }

    /**
     * Obtain the maximum.
     * @return the maximum
     */
    public Number getMaximum() {
        return theMaximum;
    }

    /**
     * Obtain the minimum.
     * @return the minimum
     */
    public Number getMinimum() {
        return theMinimum;
    }

    /**
     * is the range unbounded?
     * @return true/false
     */
    public boolean unBounded() {
        return isZero(theMinimum) && isZero(theMaximum);
    }

    /**
     * is the number zero?
     * @param pNumber the number
     * @return true/false
     */
    static boolean isZero(final Number pNumber) {
        return pNumber instanceof Double
               ? pNumber.doubleValue() == 0.0
               : pNumber.longValue() == 0;
    }

    /**
     * Does this range use floats?
     * @return true/false
     */
    public boolean isFloat() {
        return theMinimum instanceof Double;
    }

    /**
     * Parse range.
     * @param pRangeDef the range representation
     * @return the range
     * @throws ArduinoParserException on error
     */
    static ArduinoSignalRange parseRange(final String pRangeDef) throws ArduinoParserException {
        /* Remove surrounding brackets */
        if (pRangeDef.charAt(0) != START
                || pRangeDef.charAt(pRangeDef.length() - 1) != END) {
            throw new ArduinoParserException("Missing surrounding []s", pRangeDef);
        }
        final String myFactors = pRangeDef.substring(1, pRangeDef.length() - 1);

        /* Split out factors */
        final int myIndex = myFactors.indexOf(ArduinoChar.PIPE);
        if (myIndex == -1) {
            throw new ArduinoParserException("Missing " + ArduinoChar.PIPE + " separator", pRangeDef);
        }

        /* Parse the numbers */
        final String myMin = myFactors.substring(0, myIndex);
        final String myMax = myFactors.substring(myIndex + 1);
        Number myMinimum = ArduinoParser.parseNumber(myMin);
        Number myMaximum = ArduinoParser.parseNumber(myMax);

        /* Make sure that if either value is double, both are */
        if (myMinimum.getClass() != myMaximum.getClass()) {
            /* Convert longs to doubles */
            if (myMinimum instanceof Long) {
                myMinimum = myMinimum.doubleValue();
            }
            if (myMaximum instanceof Long) {
                myMaximum = myMaximum.doubleValue();
            }
        }

        /* return the parsed Range */
        return new ArduinoSignalRange(myMinimum, myMaximum);
    }

    @Override
    public String toString() {
        return "" + START + theMinimum + ArduinoChar.PIPE + theMaximum + END;
    }
}