var defaultEmptyOK = true;
var decimalPointDelimiter = ".";

// whitespace characters
var whitespace = " \t\n\r";

// Returns true if character c is a digit
// (0 .. 9).

function isDigit(c)
{
    return ((c >= "0") && (c <= "9"));
}

// Check whether string s is empty.
function isEmpty(s)
{
    return (s == null) || (s.length == 0);
}
function isEmptyAfterTrim(str)
{
    if(str == null)
        return true;
    var s = stripWhitespace(str);
    return (s == null) || (s.length == 0);
}

// isInteger (STRING s [, BOOLEAN emptyOK])
//
// Returns true if all characters in string s are numbers.
//
// Accepts non-signed integers only. Does not accept floating
// point, exponential notation, etc.
//
// We don't use parseInt because that would accept a string
// with trailing non-numeric characters.
//
// By default, returns defaultEmptyOK if s is empty.
// There is an optional second argument called emptyOK.
// emptyOK is used to override for a single function call
//      the default behavior which is specified globally by
//      defaultEmptyOK.
// If emptyOK is false (or any value other than true),
//      the function will return false if s is empty.
// If emptyOK is true, the function will return true if s is empty.
//
// EXAMPLE FUNCTION CALL:     RESULT:
// isInteger ("5")            true
// isInteger ("")             defaultEmptyOK
// isInteger ("-5")           false
// isInteger ("", true)       true
// isInteger ("", false)      false
// isInteger ("5", false)     true
function isInteger(str)
{
    var s = stripWhitespace(str);
    var i;
    if(isEmpty(s))
        if(isInteger.arguments.length == 1) return defaultEmptyOK;
        else return (isInteger.arguments[1] == true);
    // Search through string's characters one by one
    // until we find a non-numeric character.
    // When we do, return false; if we don't, return true.
    for(i = 0; i < s.length; i++)
    {
        // Check that current character is number.
        var c = s.charAt(i);
        if(!isDigit(c)) return false;
    }
    // All characters are numbers.
    return true;
}

// isSignedInteger (STRING s [, BOOLEAN emptyOK])
//
// Returns true if all characters are numbers;
// first character is allowed to be + or - as well.
//
// Does not accept floating point, exponential notation, etc.
//
// We don't use parseInt because that would accept a string
// with trailing non-numeric characters.
//
// For explanation of optional argument emptyOK,
// see comments of function isInteger.
//
// EXAMPLE FUNCTION CALL:          RESULT:
// isSignedInteger ("5")           true
// isSignedInteger ("")            defaultEmptyOK
// isSignedInteger ("-5")          true
// isSignedInteger ("+5")          true
// isSignedInteger ("", false)     false
// isSignedInteger ("", true)      true
function isSignedInteger(str)
{
    var s = stripWhitespace(str);
    if(isEmpty(s))
        if(isSignedInteger.arguments.length == 1) return defaultEmptyOK;
        else return (isSignedInteger.arguments[1] == true);
    else
    {
        var startPos = 0;
        var secondArg = defaultEmptyOK;
        if(isSignedInteger.arguments.length > 1)
            secondArg = isSignedInteger.arguments[1];
        // skip leading + or -
        if((s.charAt(0) == "-") || (s.charAt(0) == "+"))
            startPos = 1;
        return (isInteger(s.substring(startPos, s.length), secondArg))
    }
}


// isFloat (STRING s [, BOOLEAN emptyOK])
//
// True if string s is an unsigned floating point (real) number.
//
// Also returns true for unsigned integers. If you wish
// to distinguish between integers and floating point numbers,
// first call isInteger, then call isFloat.
//
// Does not accept exponential notation.
//
// For explanation of optional argument emptyOK,
// see comments of function isInteger.
function isFloat(str)
{
    var s = stripWhitespace(str);
    var i;
    var seenDecimalPoint = false;
    if(isEmpty(s))
        if(isFloat.arguments.length == 1) return defaultEmptyOK;
        else return (isFloat.arguments[1] == true);
    if(s == decimalPointDelimiter) return false;
    // Search through string's characters one by one
    // until we find a non-numeric character.
    // When we do, return false; if we don't, return true.
    for(i = 0; i < s.length; i++)
    {
        // Check that current character is number.
        var c = s.charAt(i);
        if((c == decimalPointDelimiter) && !seenDecimalPoint) seenDecimalPoint = true;
        else if(!isDigit(c))
        {
            return false;
        }
    }
    // All characters are numbers.
    return true;
}

// isSignedFloat (STRING s [, BOOLEAN emptyOK])
//
// True if string s is a signed or unsigned floating point
// (real) number. First character is allowed to be + or -.
//
// Also returns true for unsigned integers. If you wish
// to distinguish between integers and floating point numbers,
// first call isSignedInteger, then call isSignedFloat.
//
// Does not accept exponential notation.
//
// For explanation of optional argument emptyOK,
// see comments of function isInteger.
function isSignedFloat(str)
{
    var s = stripWhitespace(str);
    if(isEmpty(s))
        if(isSignedFloat.arguments.length == 1) return defaultEmptyOK;
        else return (isSignedFloat.arguments[1] == true);
    else
    {
        var startPos = 0;
        var secondArg = defaultEmptyOK;
        if(isSignedFloat.arguments.length > 1)
            secondArg = isSignedFloat.arguments[1];
        // skip leading + or -
        if((s.charAt(0) == "-") || (s.charAt(0) == "+"))
            startPos = 1;
        return (isFloat(s.substring(startPos, s.length), secondArg))
    }
}

// Removes all characters which appear in string bag from string s.
function stripCharsInBag(s, bag)
{
    var i;
    var returnString = "";
    // Search through string's characters one by one.
    // If character is not in bag, append to returnString.
    for(i = 0; i < s.length; i++)
    {
        // Check that current character isn't whitespace.
        var c = s.charAt(i);
        if(bag.indexOf(c) == -1) returnString += c;
    }
    return returnString;
}

// Removes all whitespace characters from s.
// Global variable whitespace (see above)
// defines which characters are considered whitespace.
function stripWhitespace(s)
{
    return stripCharsInBag(s, whitespace)
}
