// FUSKER.JS // usage: // f = new fusker(uri); // for (var i = 0; i < f.limit(); i++) { // document.write(f.getURI(i)); // } // // A valid fusker URI must given for the uri parameter. // The following features are supported: // // - Ranges // A range of numbers. All numbers will be at least the width of the left-hand argument. For example: // // http://www.test.com/[001-002]/[1-4]/ // // will generate: // // http://www.test.com/001/1/ // http://www.test.com/001/2/ // http://www.test.com/001/3/ // http://www.test.com/001/4/ // http://www.test.com/002/1/ // http://www.test.com/002/2/ // http://www.test.com/002/3/ // http://www.test.com/002/4/ // // - Backreferences // A reference to a previous range. Keep in mind that BACKREFERENCES COUNT TOWARD THE RANGE COUNT. for example: // // http://www.test.com/[1-2]/[0]/[3-4]/[2]/ // // will generate: // // http://www.test.com/1/1/3/3/ // http://www.test.com/1/1/4/4/ // http://www.test.com/2/2/3/3/ // http://www.test.com/2/2/4/4/ // // - TODO // * add support for lists ([abc,def,ghi,...]) // * add support for backreferences to lists // * any bug testing whatsoever function fusker(uri) { // split up the uri into ranges and constants this.ranges = uri.match(/\[\d+-\d+\]|\[\d\]/g); this.constants = uri.split(/\[\d+-\d+\]|\[\d\]/g); // if there were no range matches, make this an empty // array to avoid problems if (!this.ranges) { this.ranges = new Array(); } // make the ranges suitable for use for (var i = 0; i < this.ranges.length; i++) { // figure out what type of range this is if (this.ranges[i].search(/\[\d+\]/) > -1) { // is a backreference // eliminate brackets this.ranges[i] = { type: 1, ref: parseInt(this.ranges[i].replace(/[\[\]]/g, '')) }; } else { // is a range // split this range var split = this.ranges[i].match(/\d+/g); // turn the original into an object // type: 0 = range, 1 = backref, 2 = list (NI) this.ranges[i] = { type: 0, start: parseInt(split[0],10), end: parseInt(split[1],10), width: split[0].length, pos: 0 }; // make sure the range is sane; if start < end, swap them // i may change this in the future to allow reverse iteration if (this.ranges[i].start > this.ranges[i].end) { var tmp = this.ranges[i].start; this.ranges[i].start = this.ranges[i].end; this.ranges[i].end = tmp; } } } } fusker.prototype.limit = function() { // the limit will be at least 1 var limit = 1; // multiply by the size of each range for (var i = 0; i < this.ranges.length; i++) { // make sure this is a real range, not a backref or list if (this.ranges[i].type == 0) { limit *= this.ranges[i].end - this.ranges[i].start + 1; } } // return the number of possible values return limit; } fusker.prototype.getURI = function(pos) { var out = new String(); // figure out the proper position for each range for (var i = this.ranges.length - 1; i >= 0; i--) { // make sure this is a real range, not a backref or list if (this.ranges[i].type == 0) { // set pos to the right value this.ranges[i].pos = (this.ranges[i].start + pos % (this.ranges[i].end - this.ranges[i].start + 1)).toString(); // decrement the counter (TODO: there has to be a simpler way to do this) pos = (pos - (pos % (this.ranges[i].end - this.ranges[i].start + 1))) / (this.ranges[i].end - this.ranges[i].start + 1); // pad the value if necessary for (var j = this.ranges[i].pos.toString().length; j < this.ranges[i].width; j++) { this.ranges[i].pos = '0' + this.ranges[i].pos; } } } // assemble the string for (var i = 0; i < this.constants.length; i++) { // append a constant out += this.constants[i]; // if there are more ranges if (this.ranges[i] != undefined) { if (this.ranges[i].type == 0) { // if this range is a constant, append its value out += this.ranges[i].pos; } else if (this.ranges[i].type == 1) { // if this range is a backref, append the value it references out += this.ranges[this.ranges[i].ref].pos; } } } return out; }