Q4: тип хранилища для типов IP:
const
IPv4BitSize = SizeOf(Byte) * 4 * 8;
IPv6BitSize = SizeOf(Word) * 8 * 8;
type
T4 = 0..3;
T8 = 0..7;
TIPv4ByteArray = array[T4] of Byte;
TIPv6WordArray = array[T8] of Word;
TIPv4 = packed record
case Integer of
0: (D, C, B, A: Byte);
1: (Groups: TIPv4ByteArray);
2: (Value: Cardinal);
end;
TIPv6 = packed record
case Integer of
0: (H, G, F, E, D, C, B, A: Word);
1: (Groups: TIPv6WordArray);
end;
Q5: преобразование строк IP-адресов в эти типы записей или массивов:
function StrToIPv4(const S: String): TIPv4;
var
SIP: String;
Start: Integer;
I: T4;
Index: Integer;
Count: Integer;
SGroup: String;
G: Integer;
begin
SIP := S + '.';
Start := 1;
for I := High(T4) downto Low(T4) do
begin
Index := PosEx('.', SIP, Start);
if Index = 0 then
IPv4ErrorFmt(SInvalidIPv4Value, S);
Count := Index - Start + 1;
SGroup := Copy(SIP, Start, Count - 1);
if TryStrToInt(SGroup, G) and (G >= Low(Word)) and (G <= High(Word)) then
Result.Groups[I] := G
else
Result.Groups[I] := 0;
Inc(Start, Count);
end;
end;
function StrToIPv6(const S: String): TIPv6;
{ Valid examples for S:
2001:0db8:85a3:0000:0000:8a2e:0370:7334
2001:db8:85a3:0:0:8a2e:370:7334
2001:db8:85a3::8a2e:370:7334
::8a2e:370:7334
2001:db8:85a3::
::1
::
::ffff:c000:280
::ffff:192.0.2.128 }
var
ZeroPos: Integer;
DotPos: Integer;
SIP: String;
Start: Integer;
Index: Integer;
Count: Integer;
SGroup: String;
G: Integer;
procedure NormalNotation;
var
I: T8;
begin
SIP := S + ':';
Start := 1;
for I := High(T8) downto Low(T8) do
begin
Index := PosEx(':', SIP, Start);
if Index = 0 then
IPv6ErrorFmt(SInvalidIPv6Value, S);
Count := Index - Start + 1;
SGroup := '$' + Copy(SIP, Start, Count - 1);
if not TryStrToInt(SGroup, G) or (G > High(Word)) or (G < 0) then
IPv6ErrorFmt(SInvalidIPv6Value, S);
Result.Groups[I] := G;
Inc(Start, Count);
end;
end;
procedure CompressedNotation;
var
I: T8;
A: array of Word;
begin
SIP := S + ':';
Start := 1;
I := High(T8);
while Start < ZeroPos do
begin
Index := PosEx(':', SIP, Start);
if Index = 0 then
IPv6ErrorFmt(SInvalidIPv6Value, S);
Count := Index - Start + 1;
SGroup := '$' + Copy(SIP, Start, Count - 1);
if not TryStrToInt(SGroup, G) or (G > High(Word)) or (G < 0) then
IPv6ErrorFmt(SInvalidIPv6Value, S);
Result.Groups[I] := G;
Inc(Start, Count);
Dec(I);
end;
FillChar(Result.H, (I + 1) * SizeOf(Word), 0);
if ZeroPos < (Length(S) - 1) then
begin
SetLength(A, I + 1);
Start := ZeroPos + 2;
repeat
Index := PosEx(':', SIP, Start);
if Index > 0 then
begin
Count := Index - Start + 1;
SGroup := '$' + Copy(SIP, Start, Count - 1);
if not TryStrToInt(SGroup, G) or (G > High(Word)) or (G < 0) then
IPv6ErrorFmt(SInvalidIPv6Value, S);
A[I] := G;
Inc(Start, Count);
Dec(I);
end;
until Index = 0;
Inc(I);
Count := Length(A) - I;
Move(A[I], Result.H, Count * SizeOf(Word));
end;
end;
procedure DottedQuadNotation;
var
I: T4;
begin
if UpperCase(Copy(S, ZeroPos + 2, 4)) <> 'FFFF' then
IPv6ErrorFmt(SInvalidIPv6Value, S);
FillChar(Result.E, 5 * SizeOf(Word), 0);
Result.F := $FFFF;
SIP := S + '.';
Start := ZeroPos + 7;
for I := Low(T4) to High(T4) do
begin
Index := PosEx('.', SIP, Start);
if Index = 0 then
IPv6ErrorFmt(SInvalidIPv6Value, S);
Count := Index - Start + 1;
SGroup := Copy(SIP, Start, Count - 1);
if not TryStrToInt(SGroup, G) or (G > High(Byte)) or (G < 0) then
IPv6ErrorFmt(SInvalidIPv6Value, S);
case I of
0: Result.G := G shl 8;
1: Inc(Result.G, G);
2: Result.H := G shl 8;
3: Inc(Result.H, G);
end;
Inc(Start, Count);
end;
end;
begin
ZeroPos := Pos('::', S);
if ZeroPos = 0 then
NormalNotation
else
begin
DotPos := Pos('.', S);
if DotPos = 0 then
CompressedNotation
else
DottedQuadNotation;
end;
end;