ipv4-addr.h 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. // SPDX-License-Identifier: GPL-2.0 or GPL-3.0
  2. // Copyright © 2019 Ariadne Devos
  3. #ifndef _sHT_LEX_IPv4_ADDR
  4. #define _sHT_LEX_IPv4_ADDR
  5. #include <sHT/logic/failbit.h>
  6. /** *Perhaps* a numeric IP address parsed from a string */
  7. struct s2_ipv4_maybe
  8. {
  9. /** The IP address' numeric value
  10. Byte order: "127.0.0.1" -> 0x7f000001.
  11. The byte order of 0x7f000001 depends
  12. on the implementation of C (ABI, CPU). */
  13. uint32_t ip;
  14. /* one-past-end last last correct byte,
  15. -- if not fully parsed, the failbit is set. */
  16. sHT_with_failbit
  17. size_t end;
  18. };
  19. /** Parse a IPv4 address from an ASCII string into a number.
  20. The match is made as long as possible!
  21. If there is not match, `ret.end` is set to the first incorrect
  22. byte -- non-speculatively, all before were [0-9.] (may be useful
  23. to reduce backtracking).
  24. Requires:
  25. (a): 0 < length < failbit_limit(size_t)
  26. (* the string, not the buffer, begins at 1 *)
  27. (b): SliceCap(read ^ set, length, from)
  28. Definition:
  29. (RFC 3986, URI: Generic Syntax, 3.2.2 Host, p. 20)
  30. (* ABNF + regex-capture *)
  31. IPv4address := (dec-octet) "." (dec-octet) "." (dec-octet) "." (dec-octet)
  32. (abbreviated) IPv4address = dec-octet ("." dec-octet){3}
  33. dec-octet := [0-9] / [1-9] [0-9] / "1" [0-9]{2} / "2" [0-4][0-9] / "25" [0-5]
  34. (* dec-octet is interpreted as a natural < 256 (see <sHT/lex/nat.h>),
  35. IPv4address is formed by concatenating the `dec-octet`s into a uint32_t.
  36. *)
  37. end := maximalise (noexist → 0) {k | 1 ≤ k ≤ length }
  38. [\0, \1, \2, \3] <- do match IPv4address from 1 length
  39. value := (mappend . (map (->octet . ->nat)) [\0 .. \3]
  40. Ensures:
  41. (v): 0 ≤ fail_value(size_t, ret.end) ≤ length
  42. (w): nonspec: end ≠ 0 ↔ good(size_t, ret.end)
  43. (x): nonspec: good(size_t, ret.end) → fail_value(size_t, ret.end) = end
  44. (y): nonspec: good(size_t, ret.end) → ret.ip = value
  45. (z): nonspec: ¬good(size_t, ret.end)
  46. → match [0-9.]* from 1 fail_value(size_t, ret.end) */
  47. __attribute__((pure))
  48. struct s2_ipv4_maybe
  49. s2_parse_ipv4(size_t length, const uint8_t from[length]);
  50. #endif