/**
* @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;
};