#include "src/arpa/inet/inet_aton.h"
#include "src/__support/common.h"
#include "src/__support/endian_internal.h"
#include "src/__support/str_to_integer.h"
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(int, inet_aton, (const char *cp, in_addr *inp)) {
constexpr int IPV4_MAX_DOT_NUM = 3;
unsigned long parts[IPV4_MAX_DOT_NUM + 1] = {0};
int dot_num = 0;
for (; dot_num <= IPV4_MAX_DOT_NUM; ++dot_num) {
auto result = internal::strtointeger<unsigned long>(cp, 0);
parts[dot_num] = result;
if (result.has_error() || result.parsed_len == 0)
return 0;
char next_char = *(cp + result.parsed_len);
if (next_char != '.' && next_char != '\0')
return 0;
else if (next_char == '\0')
break;
else
cp += (result.parsed_len + 1);
}
if (dot_num > IPV4_MAX_DOT_NUM)
return 0;
unsigned long result = 0;
for (int i = 0; i <= dot_num; ++i) {
unsigned long max_part =
i == dot_num ? (0xffffffffUL >> (8 * dot_num)) : 0xffUL;
if (parts[i] > max_part)
return 0;
int shift = i == dot_num ? 0 : 8 * (IPV4_MAX_DOT_NUM - i);
result |= parts[i] << shift;
}
if (inp)
inp->s_addr = Endian::to_big_endian(static_cast<uint32_t>(result));
return 1;
}
}