// Copyright (c) 1996-2002 Brian D. Carlstrom

package bdc.scheme.procedure;

import bdc.scheme.Scheme;
import bdc.scheme.exception.ArgumentTypeException;
import bdc.scheme.Stack;
import bdc.scheme.expression.Procedure1;

/**
    (string->number x) (string->number x y)
*/
public class String2Number extends Procedure1
{
    public Object apply1 (Stack stack) throws ArgumentTypeException
    {
        Object o1 = stack.array[stack.inUse-1];
        return string2Number(Scheme.string(o1, this));
    }

    public Object apply2 (Stack stack) throws ArgumentTypeException
    {
        Object o1 = stack.array[stack.inUse-1];
        Object o2 = stack.array[stack.inUse-2];
        return string2Number(Scheme.string(o1, this),
                             Scheme.integer(o2, this));
    }

    public static Object string2Number (String string)
    {
        return string2Number(string, 10);
    }

    /**
        Shared string2Number routine. Bummed for perfomance
    */
    public static Object string2Number (String string, int radix)
    {
        /* Java thinks this is 0 or something otherwise */
        if (string.length() == 0) {
            return Boolean.FALSE;
        }

        /* Quick check to avoid exception overhead */
        if (!((Character.isDigit(string.charAt(0))) ||
              (string.charAt(0) == '.') ||
              (string.charAt(0) == '-')))
            return Boolean.FALSE;

        /* Java thinks this is 0 or something otherwise */
        if (string.equals("-")) {
            return Boolean.FALSE;
        }

        /* First try integer */
        try {
            /* check for dot otherwise 1.0 = 1 */
            if (string.indexOf('.') == -1) {
                Integer i = Integer.valueOf(string, radix);
                return i;
            }
            /* "." check failed so try double */
            try {
                Double d = Double.valueOf(string);
                return d;
            }
            /* give up */
            catch (NumberFormatException de) {
                return Boolean.FALSE;
            }
        }
        /* integer failed try double */
        catch (NumberFormatException ie) {
            try {
                Double d = Double.valueOf(string);
                return d;
            }
            /* give up */
            catch (NumberFormatException de) {
                return Boolean.FALSE;
            }
        }
    }
}
