Skip to content

Instantly share code, notes, and snippets.

@petsel
Created June 13, 2016 19:35
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save petsel/043349f345e990d002d532c06cb66f3d to your computer and use it in GitHub Desktop.
Save petsel/043349f345e990d002d532c06cb66f3d to your computer and use it in GitHub Desktop.
composable("composites.Range", function (require, global) {
"use strict";
require("environment_extended_introspective_core");
var
environment = require("environment"),
environment_introspective = environment.introspective,
environment_helpers = environment.helpers,
Object = global.Object,
String = global.String,
Number = global.Number,
Math = global.Math,
isFinite = global.isFinite,
isObject = environment_introspective.isObject,
isFunction = environment_introspective.isFunction,
isBoolean = environment_introspective.isBoolean,
isNumber = environment_introspective.isNumber,
isString = environment_introspective.isString,
compareTypes = environment_helpers.compareTypes,
object_keys = Object.keys,
object_isEqual = Object.isEqual,
isPrototypeOf = Object.isPrototypeOf,
fromCharCode = String.fromCharCode,
floor = Math.floor,
INTEGER_MINIMUM = Math.pow(-2, 53), // (Math.pow(-2, 53) - 1) === (Math.pow(-2, 53)) // true // (Math.pow(-2, 53) + 1) === (Math.pow(-2, 53)) // false
INTEGER_MAXIMUM = Math.pow(2, 53), // - see [http://blog.vjeux.com/2010/javascript/javascript-max_int-number-limits.html]
// - via [http://stackoverflow.com/questions/307179/what-is-javascripts-max-int-whats-the-highest-integer-value-a-number-can-go-to#answer-4375743]
UNDEFINED_VALUE,
REGX_RANGELIKE = (/\[[^.]+\.{2}[^.]+\]/),
getSanitizedInteger = function (type) {
return (isFinite(type = Number(type)) && ((type = floor(type)) <= INTEGER_MAXIMUM) && (type >= INTEGER_MINIMUM)) ? type : UNDEFINED_VALUE;
},
isEqualType = function (typeA, typeB) {
var
isEqual = false
;
if (isFunction(typeA.equals)) {
isEqual = typeA.equals(typeB);
} else if (isFunction(typeB.equals)) {
isEqual = typeB.equals(typeA);
}
if (!isEqual) {
isEqual = object_isEqual(typeA, typeB);
}
return isEqual;
},
isIteratorItemLike = function (type) {
return (
('value' in type)
&& (isBoolean(type.done))
&& (object_keys(type).length === 2)
);
}
;
function compareNumbers(a, b) {
return (a - b);
}
function compareStrings(a, b) {
return (((a < b) && -1) || ((a > b) && 1) || 0);
}
function getNextInteger(int) {
var
currVal = getSanitizedInteger(int),
nextVal = (currVal + 1)
;
//Math.pow(2, 53) === Math.pow(2, 53) // true
//Math.pow(2, 53) + 1 === Math.pow(2, 53) // true
//Math.pow(2, 53) + 2 === Math.pow(2, 53) // false
return ((isFinite(nextVal) && (nextVal !== currVal)) ? nextVal : UNDEFINED_VALUE);
}
function getNextIntegerInRange(int, intEnd) {
return {
value : (int = getNextInteger(int)),
done : ((int === UNDEFINED_VALUE) || (compareNumbers(int, intEnd) >= 0))
};
}
function getNextCharacter(char) {
var
currVal = ("" + char),
nextVal
;
if (currVal.length == 1) { // this definitely is a character.
/**
* as for >> (currVal === "") << ...
* ... there is nothing like a "next" character
* that could be a successor of an empty string.
*/
nextVal = fromCharCode(currVal.charCodeAt(0) + 1);
/*
* either "nextVal" gets assigned a valid character ...
* ... or assignement of "nextVal" falls back again to the [undefined] value.
*/
nextVal = ((nextVal !== "") && (nextVal !== currVal)) ? nextVal : UNDEFINED_VALUE;
}
return nextVal;
}
function getNextCharacterInRange(char, charEnd) {
return {
value : (char = getNextCharacter(char)),
done : ((char === UNDEFINED_VALUE) || (compareStrings(char, charEnd) >= 0))
};
}
function hasNextGenericItemInRange(typeA, typeB) { // fallback via build in default comparison.
return (
(compareTypes(typeA, typeB) < 0)
|| (!isEqualType(typeA, typeB))
);
}
function getNextGenericItemInRange(type, typeEnd, hasNext) {
var
tupel
;
type = type.next();
if (isIteratorItemLike(type)) {
tupel = type;
} else {
tupel = {
value : type,
done : !hasNext(type, typeEnd)
}
}
return tupel;
}
function toString(type, typeEnd, tupel) {
return [
'{[ '
, type
, ' .. '
, typeEnd
, ' ], { value: '
, tupel.value
, ', done: '
, tupel.done
, ' }}'
].join("");
}
function toValue(tupel) {
return {
value : tupel.value,
done : tupel.done
};
}
function isRangeLike(type) {
return (
isFunction(type.next)
&& REGX_RANGELIKE.test(type.toString())
);
}
function isRange(type) {
return ((type instanceof Range) || isRangeLike(type));
}
function Range(type, typeEnd, hasNext, getNext, isInitiallyDone) { // Constructor.
var
tupel = {
value : type,
done : !!isInitiallyDone
},
range = this
;
range.next = function () {
if (!tupel.done) {
tupel = getNext(tupel.value, typeEnd, hasNext);
}
return tupel;
};
range.toString = function () {
return toString(type, typeEnd, tupel);
};
range.valueOf = function () {
return toValue(tupel);
};
}
function createRange(config) { // Factory.
var
typeBegin = config.begin,
typeEnd = config.end,
compare = config.compare, // custom.
equals = config.equals, // custom.
hasNext = hasNextGenericItemInRange, // default.
range
;
if (isObject(typeBegin) && isObject(typeEnd)) {
if (
isFunction(typeBegin.next)
&& isFunction(typeEnd.next)
&& (isPrototypeOf(typeBegin) === isPrototypeOf(typeEnd))
) {
if (isFunction(compare)) {
hasNext = (function (compare) {
return function (typeA, typeB) {
return (compare(typeA, typeB) < 0);
};
}(compare));
} else if (isFunction(equals)) {
hasNext = (function (equals) {
return function (typeA, typeB) {
return (!equals(typeA, typeB));
};
}(equals));
}
range = (new Range(typeBegin, typeEnd, hasNext, getNextGenericItemInRange));
}
} else if (
isString(typeBegin)
&& (typeBegin.length === 1)
&& ((typeEnd = ("" + typeEnd)) && (typeEnd.length === 1))
&& (compareStrings(typeBegin, typeEnd) < 0)
) {
range = (new Range(typeBegin, typeEnd, hasNext, getNextCharacterInRange));
} else if (
isNumber(typeBegin)
&& ((typeBegin = getSanitizedInteger(typeBegin)) !== UNDEFINED_VALUE)
&& ((typeEnd = getSanitizedInteger(typeEnd)) !== UNDEFINED_VALUE)
&& (compareNumbers(typeBegin, typeEnd) < 0)
) {
range = (new Range(typeBegin, typeEnd, hasNext, getNextIntegerInRange));
}
return (range || (new Range(typeBegin, typeEnd, hasNext, getNextGenericItemInRange, true)));
}
return { // (Factory) Module.
create : createRange,
isRange : isRange
};
});
/*
[http://closure-compiler.appspot.com/home]
- Simple - 1716 byte
composable("composites.Range",function(r,k){function y(a,c){var b=n(a),d=b+1;return{value:a=t(d)&&d!==b?d:g,done:a===g||0<=a-c}}function z(a,c){var b=""+a,d;1==b.length&&(d=A(b.charCodeAt(0)+1),d=""!==d&&d!==b?d:g);return{value:a=d,done:a===g||0<=(a<c&&-1||a>c&&1||0)}}function B(a,c){var b;(b=0>C(a,c))||(b=!1,h(a.equals)?b=a.equals(c):h(c.equals)&&(b=c.equals(a)),b||(b=D(a,c)),b=!b);return b}function u(a,c,b){var d=a=a.next();return"value"in d&&E(d.done)&&2===F(d).length?a:{value:a,done:!b(a,c)}}function l(a,c,b,d,f){var e={value:a,done:!!f};this.next=function(){e.done||(e=d(e.value,c,b));return e};this.toString=function(){return["{[ ",a," .. ",c," ], { value: ",e.value,", done: ",e.done," }}"].join("")};this.valueOf=function(){return{value:e.value,done:e.done}}}r("environment_extended_introspective_core");var v=r("environment"),m=v.introspective,p=k.Object,G=k.Number,q=k.Math,t=k.isFinite,w=m.isObject,h=m.isFunction,E=m.isBoolean,H=m.isNumber,I=m.isString,C=v.helpers.compareTypes,F=p.keys,D=p.isEqual,x=p.isPrototypeOf,A=k.String.fromCharCode,J=q.floor,K=q.pow(-2,53),L=q.pow(2,53),g,M=/\[[^.]+\.{2}[^.]+\]/,n=function(a){return t(a=G(a))&&(a=J(a))<=L&&a>=K?a:g};return{create:function(a){var c=a.begin,b=a.end,d=a.compare;a=a.equals;var f=B,e;w(c)&&w(b)?h(c.next)&&h(b.next)&&x(c)===x(b)&&(h(d)?f=function(a){return function(b,c){return 0>a(b,c)}}(d):h(a)&&(f=function(a){return function(b,c){return!a(b,c)}}(a)),e=new l(c,b,f,u)):I(c)&&1===c.length&&(b=""+b)&&1===b.length&&0>(c<b&&-1||c>b&&1||0)?e=new l(c,b,f,z):H(c)&&(c=n(c))!==g&&(b=n(b))!==g&&0>c-b&&(e=new l(c,b,f,y));return e||new l(c,b,f,u,!0)},isRange:function(a){var c;(c=a instanceof l)||(c=h(a.next)&&M.test(a.toString()));return c}}});
*/
/*
var
r, o,
TypeRange = composable.require("composites.Range")
;
r = TypeRange.create({begin: 1, end: 0});
while(!(o = r.next()).done) {
console.log("[1 .. 0].next() : ", o);
}
console.log("[1 .. 0].next() : ", o);
r = TypeRange.create({begin: 4, end: 20});
while(!(o = r.next()).done) {
console.log("[4 .. 20].next() : ", o);
}
console.log("[4 .. 20].next() : ", o);
r = TypeRange.create({begin: -4, end: "12"});
while(!(o = r.next()).done) {
console.log("[-4 .. '12'].next() : ", o);
}
console.log("[-4 .. '12'].next() : ", o);
r = TypeRange.create({begin: "_", end: "N"});
while(!(o = r.next()).done) {
console.log("['_' .. 'N'].next() : ", o);
}
console.log("['_' .. 'N'].next() : ", o);
r = TypeRange.create({begin: "N", end: "_"});
while(!(o = r.next()).done) {
console.log("['N' .. '_'].next() : ", o);
}
console.log("['N' .. '_'].next() : ", o);
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment