Я пишу библиотеку разбора HTTP (потому что я не смог найти хорошую в чистом D), и мне нужно было иметь возможность проверять IP-адреса (для поля URI), поэтому я написал пару функций дляпроверить IP-адреса:
Для IPv4:
bool isIPv4(string addr) {
int parts;
ulong idx;
foreach (i, c; addr) {
if (c == '.') {
if (i == 0) {
return false;
}
if (to!int(addr[idx..i]) > 255) {
return false;
}
parts++;
if (parts > 3) {
return false;
}
idx = i + 1;
} else if (!isDigit(c)) {
return false;
}
}
if (to!int(addr[idx..addr.length]) > 255) {
return false;
}
if (parts != 3) {
return false;
}
return true;
}
И для IPv6:
bool isIPv6(string addr) {
bool isColon, hasSeparator, hasIPv4;
int leftChunks, rightChunks, digits;
foreach (i, c; addr) {
if (isHexDigit(c)) {
digits = isColon ? 1 : digits + 1;
isColon = false;
if (digits == 1) {
if (hasSeparator) {
rightChunks++;
} else {
leftChunks++;
}
} else if (digits > 4) {
return false;
}
} else if (c == ':') {
if (isColon) {
// multiple :: separators not allowed
// as is :::
if (hasSeparator) {
return false;
}
hasSeparator = true;
} else {
isColon = true;
}
} else if (c == '.') {
if (hasSeparator) {
rightChunks--;
} else {
leftChunks--;
}
if (!isIPv4(addr[i - digits .. addr.length])) {
return false;
}
hasIPv4 = true;
break;
}
}
if (hasIPv4) {
if (hasSeparator) {
if (rightChunks + leftChunks > 5) {
return false;
}
} else if (leftChunks != 6) {
return false;
}
} else if (digits > 0) {
if (hasSeparator) {
if (rightChunks + leftChunks > 7) {
return false;
}
} else if (leftChunks != 8) {
return false;
}
}
return true;
}
Сначала я попытался создать регулярное выражение для IPv6, но это было больно,тем более что существует очень много особых случаев (::
), и я думаю, что столкнулся с ошибкой компиляции регулярного выражения, потому что она была очень длинной.Очевидно, я хотел бы использовать некоторую стандартную функцию, чтобы сделать это для меня.
FWIW, у меня был реализован валидатор IPv4 с использованием std.arrays.split, затем я решил просто сделать это таким образом, потому что в противном случаепришлось бы обнаруживать или ловить исключения из std.conv.to! int.
Большое спасибо!
Примечание
Я бы в конечном итоге хотел быпостарайтесь получить часть кода, который я написал на Фобосе, поэтому я хотел бы, чтобы код был максимально надежным.