Created
June 20, 2011 18:48
-
-
Save julesfern/1036269 to your computer and use it in GitHub Desktop.
A bit of fun for SpahQL.js - Matching ruby's range operations for strings in Javascript.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
evalStringRange: function(start, end) { | |
var results = []; | |
// Figure out if this is a reversed or symmetrical range. | |
// Another easy comparison: Symmetrical ranges have one entry | |
if(start == end) return [start]; | |
// Easy comparison: One string is shorter than the other or the range is reversed | |
if((start > end)||(start.length!=end.length)) return results; | |
// Columnar charcode indexes: | |
// integer: 48..57 == "0".."9" | |
// ucase: 65..90 == "A".."Z" | |
// lcase: 97..122 == "a".."z" | |
// We're going to treat this like a slot machine. | |
// Create an array of "locks" which are locked columns in the range. | |
var locks = []; | |
var allLocked = true; | |
for(var c=0; c<start.length; c++) { | |
var code = start.charCodeAt(c); | |
// If outside of range, lock | |
locks[c] = ((code >= 48 && code <= 57) || (code >= 65 && code <= 90) || (code >= 97 && code <= 122))? false : true; | |
allLocked = (locks[c]==true && allLocked==true); | |
// If all others are locked and this is last column, unlock | |
if(allLocked && c == start.length-1) locks[c] = false; | |
} | |
var nextWorkingCol = function(wC) { | |
for(var w=wC-1; w>-2; w--) { | |
if(locks[w] == false) return w; | |
} | |
} | |
var gen = start+""; // clone start | |
iterating: while(true) { | |
// ^^^^ | |
// When the workingCol hits -1 we know we popped a carry on the highest-order digit and maxed the string | |
// If nextString == end then we hit the range target and should break. | |
// Push the last-iterated result | |
//results.push(new Spah.SpahQL.QueryResult(null, gen)); | |
results.push(gen); | |
if(gen == end) break iterating; | |
// Iterate until carrying stops, giving us our new stop value for the next increment | |
var workingCol = nextWorkingCol(start.length), | |
carry = true, | |
next = ""; | |
carrying: while(true) { | |
// Iterate start string and push new results. Break on maxing all unlocked columns or on reaching end token. | |
// Iteration works on the lowest-order unlocked column and may generate a carry operation, which resets the current working | |
// column to its lowest value and increments the next highest-order unlocked column. This in turn may generate a carry operation. | |
// If the overall highest-order unlocked column generates a carry when incremented, then the string is maxed and the range | |
// terminates. | |
next = (function(str) { | |
// Iterates a character and generates a new string and potentially a carry. | |
var carry = false; | |
var cCode = str.charCodeAt(0); | |
var nCode; | |
if(cCode == 57) { | |
carry = true; | |
nCode = 48; | |
} | |
else if(cCode == 90) { | |
carry = true; | |
nCode = 65; | |
} | |
else if(cCode == 122) { | |
carry = true; | |
nCode = 97; | |
} | |
else if(cCode == 127) { | |
carry = true; | |
nCode = cCode; | |
} | |
else { | |
nCode = cCode+1; | |
} | |
return [String.fromCharCode(nCode), carry]; | |
})(gen.charAt(workingCol)); | |
gen = gen.split(""); gen.splice(workingCol,1,next[0]); gen = gen.join(""); | |
if(next[1]==true) { | |
// Next next highest-order unlocked col | |
workingCol = nextWorkingCol(workingCol); | |
if(workingCol < 0) break iterating; | |
} | |
else { | |
break carrying; | |
} | |
} | |
} | |
return results; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment