#ifndef NUMBER_H
#define NUMBER_H
nonnull((1,3))
static really_inline int32_t scan_int8(
const char *data, size_t length, uint8_t *number)
{
uint32_t sum = (uint8_t)data[0] - '0';
if (sum > 9 || !length || length > 3)
return 0;
for (size_t count=1; count < length; count++) {
const uint8_t digit = (uint8_t)data[count] - '0';
sum = sum * 10 + digit;
if (digit > 9)
return 0;
}
*number = (uint8_t)sum;
return sum <= 255u;
}
nonnull((1,3))
static really_inline int32_t scan_int16(
const char *data, size_t length, uint16_t *number)
{
uint32_t sum = (uint8_t)data[0] - '0';
if (sum > 9 || !length || length > 5)
return 0;
for (size_t count=1; count < length; count++) {
const uint8_t digit = (uint8_t)data[count] - '0';
sum = sum * 10 + digit;
if (digit > 9)
return 0;
}
*number = (uint16_t)sum;
return sum <= 65535u;
}
nonnull((1,3))
static really_inline int32_t scan_int32(
const char *data, size_t length, uint32_t *number)
{
uint64_t sum = (uint8_t)data[0] - '0';
if (sum > 9 || !length || length > 10)
return 0;
for (size_t count=1; count < length; count++) {
const uint8_t digit = (uint8_t)data[count] - '0';
sum = sum * 10 + digit;
if (digit > 9)
return 0;
}
*number = (uint32_t)sum;
return sum <= 4294967295u;
}
nonnull((1,3))
static really_inline int32_t scan_int64(
const char *data, size_t length, uint64_t *number)
{
uint64_t sum = (uint8_t)data[0] - '0';
if (sum > 9 || !length || length > 20)
return 0;
for (size_t count=1; count < length; count++) {
const uint8_t digit = (uint8_t)data[count] - '0';
sum = sum * 10 + digit;
if (digit > 9)
return 0;
}
*number = sum;
return 1;
}
nonnull_all
static really_inline int32_t parse_int8(
parser_t *parser,
const type_info_t *type,
const rdata_info_t *field,
rdata_t *rdata,
const token_t *token)
{
uint8_t number;
if (!scan_int8(token->data, token->length, &number))
SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type));
*rdata->octets++ = number;
return 0;
}
nonnull_all
static really_inline int32_t parse_int16(
parser_t *parser,
const type_info_t *type,
const rdata_info_t *field,
rdata_t *rdata,
const token_t *token)
{
uint16_t number;
if (!scan_int16(token->data, token->length, &number))
SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type));
number = htobe16(number);
memcpy(rdata->octets, &number, 2);
rdata->octets += 2;
return 0;
}
nonnull_all
static really_inline int32_t parse_int32(
parser_t *parser,
const type_info_t *type,
const rdata_info_t *field,
rdata_t *rdata,
const token_t *token)
{
uint32_t number;
if (!scan_int32(token->data, token->length, &number))
SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type));
number = htobe32(number);
memcpy(rdata->octets, &number, 4);
rdata->octets += 4;
return 0;
}
nonnull_all
static really_inline int32_t parse_int64(
parser_t *parser,
const type_info_t *type,
const rdata_info_t *field,
rdata_t *rdata,
const token_t *token)
{
uint64_t number;
if (!scan_int64(token->data, token->length, &number))
SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type));
number = htobe64(number);
memcpy(rdata->octets, &number, 8);
rdata->octets += 8;
return 0;
}
#endif