diff -uNr a/udp/libudp/udp.adb b/udp/libudp/udp.adb --- a/udp/libudp/udp.adb de0cec9ced66f9d083e9c7dd1f2e02586e36481701f3b8c988f500f521454dc8ca51797961e1e773edffb7a96ad6d9b4f277b47aab056b7e313c23b8677baff3 +++ b/udp/libudp/udp.adb fac6c1240a87ba4838ee02af197f58392fb7833b40a9841716653d9d468b18c37201585a66bc2133c8f2f5c60bdc0364291a64b91ae301281ecec416dad6c57f @@ -22,31 +22,53 @@ -- Generate a human representation of a (local-endian) IP Address function IP_To_String(IP : in IP_Address) return IP_Address_Text is Text : IP_Address_Text := (others => ' '); - begin - Unix_UDP_IP_To_String(IP, Text'Address, Text'Length); + I : Integer := Text'First; + W : IP_Address := IP; + D : IP_Address := 256 ** 3; + begin + for J in Integer range 1 .. 4 loop + declare + P : IP_Address := (W / D) mod 256; + begin + I := write_mod1000_to_string(P, Text, I); + if J < 4 then + Text(I) := '.'; + I := I + 1; + end if; + W := W mod D; + D := D / 256; + end; + end loop; return Text; end IP_To_String; -- Generate a (local-endian) IP Address from given human representation function IP_From_String(IP_Text : in String) return IP_Address is - Text_With_Null : String(1 .. IP_Text'Length + 1); - Result : Interfaces.C.Int := 0; - IP : aliased IP_Address; - begin - -- We can't use To_C because malicious idiots demanded secondary stack. - Text_With_Null(IP_Text'Range) := IP_Text; - Text_With_Null(Text_With_Null'Last) := Character'Val(0); - - -- Let unix do the conversion - Result := Unix_UDP_String_To_IP(Text_With_Null'Address, - IP'Access); - case Result is - when -1 => - raise UDP_Invalid_Text_IP; - when others => - return IP; - end case; + I : Integer := IP_Text'First; + V : Natural := 0; + begin + for J in Integer range 1 .. 4 loop + declare + P : Natural := 0; + K : constant Integer := read_mod1000_from_string(P, IP_Text, I); + begin + --- If nothing was read --> error + if K = I then + raise UDP_Invalid_Text_IP; + end if; + I := K; + + if J < 4 then + if IP_Text(I) /= '.' then + raise UDP_Invalid_Text_IP; + end if; + I := I + 1; + end if; + V := V * 256 + P; + end; + end loop; + return IP_Address(V); end IP_From_String; @@ -138,5 +160,69 @@ end if; end case; end Receive; + + -- Support functions for string and ip address conversions + + -- Function to read a number between 0 - 999 from a given string. + -- Reading will finish when 3 digits are read or a non number is encounter + function read_mod1000_from_string + (V : out Natural; + S : in String; + INDEX : in Integer) return Integer is + I : Integer := INDEX; + begin + V := 0; + while I < INDEX + 3 and I < S'Last+1 loop + declare + CH : constant Character := S(I); + P : Natural := 0; + begin + case CH is + when '0' => P := 0; + when '1' => P := 1; + when '2' => P := 2; + when '3' => P := 3; + when '4' => P := 4; + when '5' => P := 5; + when '6' => P := 6; + when '7' => P := 7; + when '8' => P := 8; + when '9' => P := 9; + when others => exit; + end case; + V := V * 10 + P; + I := I + 1; + end; + end loop; + return I; + end read_mod1000_from_string; + + + -- Function to write a number between 0 - 999 to a given string. + -- Each number will be written left aligned, + -- tens and hunderds will be printed if any. + -- The number will be written starting from the value of index, + -- will return the next index after the last written digit. + function write_mod1000_to_string + (V : in IP_Address; + S : in out String; + INDEX : in Integer) return Integer is + I : Integer := INDEX; + Z : constant IP_Address := Character'Pos('0'); + A : constant IP_Address := (V / 100) mod 10; + B : constant IP_Address := (V mod 100) / 10; + C : constant IP_Address := (V mod 10); + begin + if A > 0 then + S(I) := Character'Val(Z+A); + I := I + 1; + end if; + if B > 0 then + S(I) := Character'Val(Z+B); + I := I + 1; + end if; + S(I) := Character'Val(Z+C); + return I + 1; + end write_mod1000_to_string; end UDP; diff -uNr a/udp/libudp/udp.ads b/udp/libudp/udp.ads --- a/udp/libudp/udp.ads 41d0512d8759cbcb10d753a22a86b6bdaf96fccf779e2bbdabf4a1c7efca7a4f8f9047984d6cc2350b7625715aac26c0ccd49c7baca765811e0c0bcc0ababf22 +++ b/udp/libudp/udp.ads 257085592c6440e74e1f64ce625940e6c61fd1bec56fdef327a8fc17d58578caadbe041a0d4f16c71abeff2192b19a64ff25959d76685509a0c2d3c2b030f502 @@ -145,5 +145,17 @@ Payload_Buf : System.Address; Payload_Len : Unsigned_32) return Interfaces.C.int; pragma Import(C, Unix_UDP_Socket_Receive, "unix_udp_socket_receive"); + + -- Support functions for conversion between a string and an ip-address + function read_mod1000_from_string + (V : out Natural; + S : in String; + INDEX : in Integer) return Integer; + + function write_mod1000_to_string + (V : in IP_Address; + S : in out String; + INDEX : in Integer) return Integer; + end UDP; diff -uNr a/udp/manifest b/udp/manifest --- a/udp/manifest c2719877ad84bd2cf788458df5eb16341e0151e867afa8b8b20faf9f10a8b1723123f19b581dab0627458350e6ab26be87ec84ac94f80f29d61778df5705a969 +++ b/udp/manifest 135461b32061a95d3ab747a510040dbfa72040dd628dc8609fc213ef1c2f74d6c78c72df53f14ea592cd7757a16f14c4f57e89dda9ba9ef738cbee76f3ff6fd1 @@ -1,2 +1,3 @@ 543080 udp_genesis diana_coman Regrind of asciilifeform's UDP lib genesis, to bring it to current format (Keccak hashes, manifest file and standard compliant names for vpatches). A minimal library for UDP communications with fixed-size payloads sent/received over the wire. Uses Ada and C code. 543081 udp_errata_asciilifeform diana_coman Regrind of asciilifeform's errata on his UDP lib: adds closing socket calls, corrects and adds to comments. +543909 custom_conversion_ave1 Use Ada based function to convert from ip address to string and vice versa.