# Source: is2.js

    /**
     * @fileOverview
     * is2 derived from is by Enrico Marino, adapted for Node.js.
     * License remains the same.
     * Slightly modified by Edmond Meinfelder
     *
     * is
     * the definitive JavaScript type testing library
     * Copyright(c) 2011 Enrico Marino <enrico.marino@email.com>
     * MIT license
     */
    'use strict';
    var owns = {}.hasOwnProperty;
    var toString = {}.toString;

    /**
     * @constant
     * Library version.
     */
    exports.version = '0.1.5';

    /**
     * @name type
     * Test if 'value' is a type of 'type'.
     * Alias: a
     * @param value value to test.
     * @param {String} type type.
     * @returns {Boolean} true if 'value' is an arguments object, false otherwise.
     * @public
     */
    exports.a =
    exports.type = function (value, type) {
        return typeof value === type;
    };

    /**
     * @name defined
     * Test if 'value' is defined.
     * Alias: def
     * @param value value to test.
     * @returns {Boolean} true if 'value' is defined, false otherwise.
     * @public
     */
    exports.def =
    exports.defined = function (value) {
        return typeof value !== 'undefined';
    };

    /**
     * @name nullOrUndefined
     * Test is 'value' is either null or undefined.
     * Alias: nullOrUndef
     * @param value value to test.
     * @returns {Boolean} True if value is null or undefined, false otherwise.
     * @public
     */
    exports.nullOrUndefined =
    exports.nullOrUndef = function(value) {
        return value === null || typeof value === 'undefined';
    };

    /**
     * @name empty
     * Test if 'value' is empty. To be empty means to be an array, object or string with nothing contained.
     * @param value value to test.
     * @returns {Boolean} true if 'value' is empty, false otherwise.
     * @public
     */
    exports.empty = function (value) {
        var type = toString.call(value);

        if ('[object Array]' === type || '[object Arguments]' === type) {
            return value.length === 0;
        }

        if ('[object Object]' === type) {
            for (var key in value) if (owns.call(value, key)) return false;
            return true;
        }

        if ('[object String]' === type) {
            return value === '';
        }

        return false;
    };

    /**
     * @name objEquals
     * Do a deep comparision of two objects for equality. Will recurse without any limits. Meant to be
     * called by equal only.
     * @param {Object} value The first object to compare.
     * @param {Object} other The second object to compare.
     * @returns {Boolean} true, if the objects are equivalent, false otherwise.
     * @private
     */
    exports.objEquals = function (value, other) {
        var key;

        for (key in other) {
            // ensure all the keys that exist in obj, exist in otherObj
            if (typeof other[key] !== 'undefined' && typeof (other[key]) === 'undefined') {
                return false;
            }

            // if the types don't match, there is no equivalance
            if (typeof other[key] !== typeof (other[key])) {
                return false;
            }

            // The types match, so we need to see if we have to do a deep check
            switch (typeof (other[key])) {
            case 'object':
                if (exports.array(other[key])) {
                    if (!exports.array(value[key])) {
                        return false;
                    }
                    if (value.length !== other.length) {
                        return false;
                    }
                    var len = other.length;
                    while (--len) {
                        if (value[len] !== other[len]) {
                            return false;
                        }
                    }
                } else {
                    if (!exports.equal(other[key], value[key])) {
                        return false;
                    }
                }
                break;
            case 'function':
                if (typeof (value[key]) === 'undefined' ||
                  (key !== 'equals' && other[key].toString() !== value[key].toString())) {
                    return false;
                }
                break;
            default:
                if (other[key] !== value[key]) {
                    return false;
                }
                break;
            }
        }

        for (key in value) {
            if (typeof (other[key]) === 'undefined') {
                return false;
            }
        }

        return true;
    };

    /**
     * @name equal
     * Test if 'value' is equal to 'other'. Works for objects and arrays and will do deep comparisions,
     * using recursion.
     * Alias: eq
     * @param value value.
     * @param other value to compare with.
     * @returns {Boolean} true if 'value' is equal to 'other', false otherwise
     * @public
     */
    exports.eq =
    exports.equal = function (value, other) {
        var type = toString.call(value);

        if (typeof value !== typeof other) {
            return false;
        }

        if (type !== toString.call(other)) {
            return false;
        }

        if ('[object Object]' === type) {
            return exports.objEquals(value, other);
        } else if ('[object Array]' === type) {
            var index = value.length;
            if (index !== other.length) {
                return false;
            }
            while (--index > -1) {
                if (!exports.equal(value[index], other[index])) {
                    return false;
                }
            }
            return true;

        } else if ('[object Function]' === type) {
            return value.prototype === other.prototype;
        } else if ('[object Date]' === type) {
            return value.getTime() === other.getTime();
        }

        return value === other;
    };

    /**
     * @name hosted
     * Test if 'key' in host is an object. To be hosted means host[value] is an object.
     * @param {String} value to test.
     * @param host host that may contain value.
     * @returns {Boolean} true if 'value' is hosted by 'host', false otherwise.
     * @public
     */
    var NON_HOST_TYPES = {
          'boolean': 1
        , 'number': 1
        , 'string': 1
        , 'undefined': 1
    };

    exports.hosted = function (value, host) {
        if (exports.nullOrUndef(value))
            return false;
        var type = typeof host[value];
        return type === 'object' ? !!host[value] : !NON_HOST_TYPES[type];
    };

    /**
     * @name instanceOf
     * Test if 'value' is an instance of 'constructor'.
     * Aliases: instOf, instanceof
     * @param value value to test.
     * @returns {Boolean} true if 'value' is an instance of 'constructor'.
     * @public
     */
    exports.instOf =
    exports.instanceof =
    exports.instanceOf = function (value, constructor) {
        if (exports.nullOrUndef(value) || exports.nullOrUndef(constructor))
            return false;
        return (value instanceof constructor);
    };

    /**
     * @name null
     * Test if 'value' is null.
     * @param value to test.
     * @returns {Boolean} true if 'value' is null, false otherwise.
     * @public
     */
    exports.null = function (value) {
        return value === null;
    };

    /**
     * @name undefined
     * Test if 'value' is undefined.
     * Aliases: undef, udef
     * @param value value to test.
     * @returns {Boolean} true if 'value' is undefined, false otherwise.
     * @public
     */
    exports.udef =
    exports.undef =
    exports.undefined = function (value) {
        return value === undefined;
    };

    /**
     * @name arguments
     * Test if 'value' is an arguments object.
     * Alias: args
     * @param value value to test
     * @returns {Boolean} true if 'value' is an arguments object, false otherwise
     * @public
     */
    exports.args =
    exports.arguments = function (value) {
        return '[object Arguments]' === toString.call(value);
    };

    /**
     * @name array
     * Test if 'value' is an array.
     * Alias: ary, arry
     * @param value value to test.
     * @returns {Boolean} true if 'value' is an array, false otherwise.
     * @public
     */
    exports.ary =
    exports.arry =
    exports.array = function (value) {
        return '[object Array]' === toString.call(value);
    };

    /**
     * @name nonEmptyArray
     * Test if 'value' is an array containing at least 1 entry.
     * Aliases: nonEmptyArry, nonEmptyAry
     * @param value value to test.
     * @returns {Boolean} true if 'value' is an array with at least 1 value, false otherwise.
     * @public
     */
    exports.nonEmptyArry =
    exports.nonEmptyAry =
    exports.nonEmptyArray = function (value) {
        return '[object Array]' === toString.call(value) && value.length > 0;
    };

    /**
     * @name array.empty
     * Test if 'value' is an empty array(like) object.
     * Aliases: arguents.empty, args.empty, ary.empty, arry.empty
     * @param {Array|Arguments} value value to test.
     * @returns {Boolean} true if 'value' is an empty array(like), false otherwise.
     * @public
     */
    exports.arguments.empty =
    exports.args.empty =
    exports.ary.empty =
    exports.arry.empty =
    exports.array.empty = function (value) {
        return value.length === 0;
    };

    /**
     * @name arrayLike
     * Test if 'value' is an arraylike object (i.e. it has a length property with a valid value)
     * Aliases: arraylike, arryLike, aryLike
     * @param value value to test.
     * @returns {Boolean} true if 'value' is an arguments object, false otherwise.
     * @public
     */
    exports.arryLike =
    exports.aryLike =
    exports.arraylike =
    exports.arrayLike = function (value) {
        if (exports.nullOrUndef(value))
            return false;
        return value !== undefined &&
            owns.call(value, 'length') &&
            isFinite(value.length);
    };

    /**
     * @name boolean
     * Test if 'value' is a boolean.
     * Alias: bool
     * @param value value to test.
     * @returns {Boolean} true if 'value' is a boolean, false otherwise.
     * @public
     */
    exports.bool =
    exports.boolean = function (value) {
        return '[object Boolean]' === toString.call(value);
    };

    /**
     * @name false
     * Test if 'value' is false.
     * @param value value to test.
     * @returns {Boolean} true if 'value' is false, false otherwise
     * @public
     */
    exports.false = function (value) {
        return value === false;
    };

    /**
     * @name true
     * Test if 'value' is true.
     * @param {Boolean} value to test.
     * @returns {Boolean} true if 'value' is true, false otherwise.
     * @public
     */
    exports.true = function (value) {
        return value === true;
    };

    /**
     * @name date
     * Test if 'value' is a date.
     * @param value value to test.
     * @returns {Boolean} true if 'value' is a date, false otherwise.
     * @public
     */
    exports.date = function (value) {
        return '[object Date]' === toString.call(value);
    };

    /**
     * @name error
     * Test if 'value' is an error object.
     * Alias: err
     * @param value value to test.
     * @returns {Boolean} true if 'value' is an error object, false otherwise.
     * @public
     */
    exports.err =
    exports.error = function (value) {
        return '[object Error]' === toString.call(value);
    };

    /**
     * @name function
     * Test if 'value' is a function.
     * Alias: func
     * @param value value to test.
     * @returns {Boolean} true if 'value' is a function, false otherwise.
     * @public
     */
    exports.func =
    exports.function = function(value) {
        return '[object Function]' === toString.call(value);
    };

    /**
     * @name number
     * Test if 'value' is a number.
     * Alias: num
     * @param value to test.
     * @returns {Boolean} true if 'value' is a number, false otherwise.
     * @public
     */
    exports.num =
    exports.number = function (value) {
        return '[object Number]' === toString.call(value);
    };

    /**
     * @name positiveNumber
     * Test if 'value' is a positive number.
     * Alias: positiveNum, posNum
     * @param value to test.
     * @returns {Boolean} true if 'value' is a number, false otherwise.
     * @public
     */
    exports.posNum =
    exports.positiveNum =
    exports.positiveNumber = function (value) {
        return '[object Number]' === toString.call(value) && value > 0;
    };

    /**
     * @name negativeNumber
     * Test if 'value' is a negative number.
     * Aliases: negNum, negativeNum
     * @param value to test.
     * @returns {Boolean} true if 'value' is a number, false otherwise.
     * @public
     */
    exports.negNum =
    exports.negativeNum =
    exports.negativeNumber = function (value) {
        return '[object Number]' === toString.call(value) && value < 0;
    };

    /**
     * @name decimal
     * Test if 'value' is a decimal number.
     * Aliases: decimalNumber, decNum
     * @param value value to test.
     * @returns {Boolean} true if 'value' is a decimal number, false otherwise.
     * @public
     */
    exports.decNum =
    exports.decNumer =
    exports.decimal = function (value) {
        return '[object Number]' === toString.call(value) && value % 1 !== 0;
    };

    /**
     * @name divisibleBy
     * Test if 'value' is divisible by 'n'.
     * Alias: divisBy
     * @param {Number} value value to test.
     * @param {Number} n dividend.
     * @returns {Boolean} true if 'value' is divisible by 'n', false otherwise.
     * @public
     */
    exports.divisBy =
    exports.divisibleBy = function (value, n) {
        if (value === 0)
            return false;
        return '[object Number]' === toString.call(value) &&
            n !== 0 &&
            value % n === 0;
    };

    /**
     * @name int
     * Test if 'value' is an integer.
     * Alias: integer
     * @param value to test.
     * @returns {Boolean} true if 'value' is an integer, false otherwise.
     * @public
     */
    exports.integer =
    exports.int = function (value) {
        return '[object Number]' === toString.call(value) && value % 1 === 0;
    };

    /**
     * @name positiveInt
     * Test if 'value' is a positive integer.
     * Alias: posInt
     * @param value to test.
     * @returns {Boolean} true if 'value' is a positive integer, false otherwise.
     * @public
     */
    exports.posInt =
    exports.positiveInteger =
    exports.positiveInt = function (value) {
        return '[object Number]' === toString.call(value) && value % 1 === 0 && value > 0;
    };

    /**
     * @name negativeInt
     * Test if 'value' is a negative integer.
     * Aliases: negInt, negativeInteger
     * @param value to test.
     * @returns {Boolean} true if 'value' is a negative integer, false otherwise.
     * @public
     */
    exports.negativeInteger =
    exports.negInt =
    exports.negativeInt = function (value) {
        return '[object Number]' === toString.call(value) && value % 1 === 0 && value < 0;
    };

    /**
     * @name maximum
     * Test if 'value' is greater than 'others' values.
     * Alias: max
     * @param {Number} value value to test.
     * @param {Array} others values to compare with.
     * @returns {Boolean} true if 'value' is greater than 'others' values.
     * @public
     */
    exports.max =
    exports.maximum = function (value, others) {
        if (!exports.arrayLike(others) || !exports.number(value))
            return false;

        var len = others.length;
        while (--len > -1) {
            if (value < others[len]) {
                return false;
            }
        }

        return true;
    };

    /**
     * @name minimum
     * Test if 'value' is less than 'others' values.
     * Alias: min
     * @param {Number} value value to test.
     * @param {Array} others values to compare with.
     * @returns {Boolean} true if 'value' is less than 'others' values.
     * @public
     */
    exports.min =
    exports.minimum = function (value, others) {
        if (!exports.arrayLike(others) || !exports.number(value))
            return false;

        var len = others.length;
        while (--len > -1) {
            if (value > others[len]) {
                return false;
            }
        }

        return true;
    };

    /**
     * @name nan
     * Test if 'value' is not a number.
     * Alias: notANumber, notANum
     * @param value to test
     * @returns {Boolean} true if 'value' is not a number, false otherwise
     * @public
     */
    exports.notANumber =
    exports.notANum =
    exports.nan = function (value) {
        return isNaN(value);
    };

    /**
     * @name even
     * Test if 'value' is an even number.
     * @param {Number} value to test.
     * @returns {Boolean} true if 'value' is an even number, false otherwise.
     * @public
     */
    exports.even = function (value) {
        return '[object Number]' === toString.call(value) && value % 2 === 0;
    };

    /**
     * @name odd
     * Test if 'value' is an odd number.
     * @param {Number} value to test.
     * @returns {Boolean} true if 'value' is an odd number, false otherwise.
     * @public
     */
    exports.odd = function (value) {
        return !exports.decimal(value) && '[object Number]' === toString.call(value) && value % 2 !== 0;
    };

    /**
     * @name ge
     * Test if 'value' is greater than or equal to 'other'.
     * Aliases: greaterOrEq, greaterOrEqual
     * @param {Number} value value to test.
     * @param {Number} other value to compare with.
     * @returns {Boolean} true, if value is greater than or equal to other, false otherwise.
     * @public
     */
    exports.ge = function (value, other) {
        return value >= other;
    };

    /**
     * @name gt
     * Test if 'value' is greater than 'other'.
     * Aliases: greaterThan
     * @param {Number} value value to test.
     * @param {Number} other value to compare with.
     * @returns {Boolean} true, if value is greater than other, false otherwise.
     * @public
     */
    exports.greaterThan =
    exports.gt = function (value, other) {
        return value > other;
    };

    /**
     * @name le
     * Test if 'value' is less than or equal to 'other'.
     * Alias: lessThanOrEq, lessThanOrEqual
     * @param {Number} value value to test
     * @param {Number} other value to compare with
     * @returns {Boolean} true, if 'value' is less than or equal to 'other', false otherwise.
     * @public
     */
    exports.lessThanOrEq =
    exports.lessThanOrEqual =
    exports.le = function (value, other) {
        return value <= other;
    };

    /**
     * @name lt
     * Test if 'value' is less than 'other'.
     * Alias: lessThan
     * @param {Number} value value to test
     * @param {Number} other value to compare with
     * @returns {Boolean} true, if 'value' is less than 'other', false otherwise.
     * @public
     */
    exports.lessThan =
    exports.lt = function (value, other) {
        return value < other;
    };

    /**
     * @name within
     * Test if 'value' is within 'start' and 'finish'.
     * Alias: withIn
     * @param {Number} value value to test.
     * @param {Number} start lower bound.
     * @param {Number} finish upper bound.
     * @returns {Boolean} true if 'value' is is within 'start' and 'finish', false otherwise.
     * @public
     */
    exports.withIn =
    exports.within = function (value, start, finish) {
        return value >= start && value <= finish;
    };

    /**
     * @name object
     * Test if 'value' is an object. Note: Arrays, RegExps, Date, Error, etc all return false.
     * Alias: obj
     * @param value to test.
     * @returns {Boolean} true if 'value' is an object, false otherwise.
     * @public
     */
    exports.obj =
    exports.object = function (value) {
        return '[object Object]' === toString.call(value);
    };

    /**
     * @name nonEmptyObject
     * Test if 'value' is an object with properties. Note: Arrays are objects.
     * Alias: nonEmptyObj
     * @param value to test.
     * @returns {Boolean} true if 'value' is an object, false otherwise.
     * @public
     */
    exports.nonEmptyObj =
    exports.nonEmptyObject = function (value) {
        return '[object Object]' === toString.call(value) && Object.keys(value).length;
    };

    /**
     * @name objectInstanceOf
     * Test if 'value' is an instance type objType.
     * Aliases: objInstOf, objectinstanceof
     * @param {object} objInst an object to testfor type.
     * @param {object} objType an object type to compare.
     * @returns {Boolean} true if 'value' is an object, false otherwise.
     * @public
     */
    exports.objInstOf =
    exports.objectInstanceOf =
    exports.objectInstanceof = function (objInst, objType) {
        return '[object Object]' === toString.call(objInst) && (objInst instanceof objType);
    };

    /**
     * @name regExp
     * Test if 'value' is a regular expression.
     * Alias: regexp
     * @param value to test.
     * @returns {Boolean} true if 'value' is a regexp, false otherwise.
     * @public
     */
    exports.regExp =
    exports.regexp = function (value) {
        return '[object RegExp]' === toString.call(value);
    };

    /**
     * @name str
     * Test if 'value' is a string.
     * Alias: str
     * @param value to test.
     * @returns {Boolean} true if 'value' is a string, false otherwise.
     * @public
     */
    exports.str =
    exports.string = function (value) {
        return '[object String]' === toString.call(value);
    };

    /**
     * @name nonEmptyStr
     * Test if 'value' is a non-empty string.
     * Alias: nonEmptyStr
     * @param value to test.
     * @returns {Boolean} true if 'value' is a non-empty string, false otherwise.
     * @public
     */
    exports.nonEmptyStr =
    exports.nonEmptyString = function (value) {
        return exports.string(value) && value.length > 0;
    };