EVOLUTION-MANAGER
Edit File: regular-expressions.js
'use strict'; var sprintf = require('sprintf-js').sprintf; var v6 = require('./constants.js'); function groupPossibilities(possibilities) { return sprintf('(%s)', possibilities.join('|')); } function padGroup(group) { if (group.length < 4) { return sprintf('0{0,%d}%s', 4 - group.length, group); } return group; } var ADDRESS_BOUNDARY = '[^A-Fa-f0-9:]'; function simpleRegularExpression(groups) { var zeroIndexes = []; groups.forEach(function (group, i) { var groupInteger = parseInt(group, 16); if (groupInteger === 0) { zeroIndexes.push(i); } }); // You can technically elide a single 0, this creates the regular expressions // to match that eventuality var possibilities = zeroIndexes.map(function (zeroIndex) { return groups.map(function (group, i) { if (i === zeroIndex) { var elision = (i === 0 || i === v6.GROUPS - 1) ? ':' : ''; return groupPossibilities([padGroup(group), elision]); } return padGroup(group); }).join(':'); }); // The simplest case possibilities.push(groups.map(padGroup).join(':')); return groupPossibilities(possibilities); } function possibleElisions(elidedGroups, moreLeft, moreRight) { var left = moreLeft ? '' : ':'; var right = moreRight ? '' : ':'; var possibilities = []; // 1. elision of everything (::) if (!moreLeft && !moreRight) { possibilities.push('::'); } // 2. complete elision of the middle if (moreLeft && moreRight) { possibilities.push(''); } if ((moreRight && !moreLeft) || (!moreRight && moreLeft)) { // 3. complete elision of one side possibilities.push(':'); } // 4. elision from the left side possibilities.push(sprintf('%s(:0{1,4}){1,%d}', left, elidedGroups - 1)); // 5. elision from the right side possibilities.push(sprintf('(0{1,4}:){1,%d}%s', elidedGroups - 1, right)); // 6. no elision possibilities.push(sprintf('(0{1,4}:){%d}0{1,4}', elidedGroups - 1)); // 7. elision (including sloppy elision) from the middle for (var groups = 1; groups < elidedGroups - 1; groups++) { for (var position = 1; position < elidedGroups - groups; position++) { possibilities.push(sprintf('(0{1,4}:){%d}:(0{1,4}:){%d}0{1,4}', position, elidedGroups - position - groups - 1)); } } return groupPossibilities(possibilities); } /** * Generate a regular expression string that can be used to find or validate * all variations of this address * @memberof Address6 * @instance * @param {string} optionalSubString * @returns {string} */ exports.regularExpressionString = function (optionalSubString) { if (optionalSubString === undefined) { optionalSubString = false; } var output = []; // TODO: revisit why this is necessary var address6 = new this.constructor(this.correctForm()); if (address6.elidedGroups === 0) { // The simple case output.push(simpleRegularExpression(address6.parsedAddress)); } else if (address6.elidedGroups === v6.GROUPS) { // A completely elided address output.push(possibleElisions(v6.GROUPS)); } else { // A partially elided address var halves = address6.address.split('::'); if (halves[0].length) { output.push(simpleRegularExpression(halves[0].split(':'))); } output.push(possibleElisions(address6.elidedGroups, halves[0].length !== 0, halves[1].length !== 0)); if (halves[1].length) { output.push(simpleRegularExpression(halves[1].split(':'))); } output = [output.join(':')]; } if (!optionalSubString) { output = [].concat( '(?=^|', ADDRESS_BOUNDARY, '|[^\\w\\:])(', output, ')(?=[^\\w\\:]|', ADDRESS_BOUNDARY, '|$)'); } return output.join(''); }; /** * Generate a regular expression that can be used to find or validate all * variations of this address. * @memberof Address6 * @instance * @param {string} optionalSubString * @returns {RegExp} */ exports.regularExpression = function (optionalSubstring) { return new RegExp(this.regularExpressionString(optionalSubstring), 'i'); };