Skip to content

Instantly share code, notes, and snippets.

@ollyg
Forked from radu-c/cidr_to_regex.js
Last active December 18, 2024 08:07
Show Gist options
  • Save ollyg/b5d0824a2876c995c67812e643505b90 to your computer and use it in GitHub Desktop.
Save ollyg/b5d0824a2876c995c67812e643505b90 to your computer and use it in GitHub Desktop.
const zip = (arr, ...arrs) => {
return arr.map((val, i) => arrs.reduce((a, arr) => [...a, arr[i]], [val]))
}
const cidrToRegex = cidr => {
const [ip, prefix] = cidr.split('/')
const base = ip
.split('.')
.map(val => parseInt(val))
.reduce((base, val) => (base << 8) | val, 0)
const shift = 32 - parseInt(prefix)
const start = (base >> shift) << shift
const end = start | ((1 << shift) - 1)
const regex = (lower, upper) => {
if (lower === upper) {
return `${lower}`
}
let exp = parseInt(Math.log10(upper - lower))
const lowerS = `${lower}`
const upperS = `${upper}`
if (lowerS.substr(-1,1) > upperS.substr(-1,1) && exp == 0) {
// increasing exp due to base 10 wrap to next exp"
exp += 1
}
const delta = 10 ** exp
if (lower === 0 && upper === 255) {
return '(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])'
}
if (delta === 1) {
let val = ''
const z = zip(lowerS.split(''), upperS.split(''))
for (const [a, b] of z) {
if (a === b) {
val += a
} else if ((a === '0' && b === '9') || (b === '0' && a === '9')) {
val += '\\d'
} else if (Math.abs(b - a) === 1) {
val += `[${a}${b}]`
} else {
if (b < a) {
val += `[${b}-${a}]`
} else {
val += `[${a}-${b}]`
}
}
}
return val
}
const floor_ = x => parseInt(Math.floor(x / delta) * delta)
const genClasses = () => {
const parts = []
const first = floor_(upper) - delta
const last = floor_(lower)
const p = Array(exp).fill('\\d').join('')
let xs = first
while (xs > last) {
const x = `${xs}`
parts.push(`${x.substr(exp - 1, 1)}${p}`)
xs -= delta
}
parts.push(regex(lower, floor_(lower) + (delta - 1)))
parts.push(regex(floor_(upper), upper))
return parts
}
return '(?:' + genClasses().join('|') + ')'
}
const getParts = () => {
const parts = []
for (let x = 24; x >= 0; x -= 8) {
parts.push(regex((start >> x) & 255, (end >> x) & 255))
}
return parts
}
return `(?:${getParts().join('\\.')})`
}
module.exports.cidrToRegex = cidrToRegex
@ollyg
Copy link
Author

ollyg commented Dec 17, 2024

This updated version of the original fixes three bugs found.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment