ustr-parse-code.h
#ifndef USTR_PARSE_H
#error " You should have already included ustr-parse.h, or just include ustr.h."
#endif
#if ! USTR_CONF_HAVE_STDINT_H
# define USTR__UMAX unsigned long
#else
# define USTR__UMAX uintmax_t
#endif
USTR_CONF_e_PROTO
int ustr__parse_num_beg(const char **ptr, size_t *len,
unsigned int flags, int *tst_neg, int *tst_0,
unsigned int *ern)
USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A();
USTR_CONF_i_PROTO
int ustr__parse_num_beg(const char **ptr, size_t *len,
unsigned int flags, int *tst_neg, int *tst_0,
unsigned int *ern)
{
unsigned int base = flags & USTR__MASK_PARSE_NUM_BASE;
int auto_base = USTR_FALSE;
if (!base)
auto_base = USTR_TRUE;
else if (base > 36)
base = 36;
else if (base == 1)
++base;
if (flags & USTR_FLAG_PARSE_NUM_SPACE)
{
while (*len && (**ptr == ' '))
{
++*ptr;
--*len;
}
if (!*len)
{
*ern = USTR_TYPE_PARSE_NUM_ERR_ONLY_S;
return (0);
}
}
if (!(flags & USTR_FLAG_PARSE_NUM_NO_BEG_PM))
{
switch (**ptr)
{
case '-':
*tst_neg = USTR_TRUE;
case '+':
++*ptr;
--*len;
}
if (!*len)
{
*ern = USTR_TYPE_PARSE_NUM_ERR_ONLY_SPM;
return (0);
}
}
if (**ptr != '0')
{
if (base)
return (base);
return (10);
}
++*ptr;
--*len;
if (!*len)
{
*tst_0 = USTR_TRUE;
return (10);
}
else if ((auto_base || (base == 2)) && ((**ptr == 'b') || (**ptr == 'B')))
base = 2;
else if ((auto_base || (base == 8)) && ((**ptr == 'o') || (**ptr == 'O')))
base = 8;
else if ((auto_base || (base == 16)) && ((**ptr == 'x') || (**ptr == 'X')))
base = 16;
else if ((flags & USTR_FLAG_PARSE_NUM_NO_BEG_ZERO) &&
(!auto_base || (**ptr == '0')))
{
*ern = USTR_TYPE_PARSE_NUM_ERR_BEG_ZERO;
return (0);
}
else
{
*tst_0 = USTR_TRUE;
if (base)
return (base);
return (8);
}
++*ptr;
--*len;
if (!*len)
{
*ern = USTR_TYPE_PARSE_NUM_ERR_ONLY_SPMX;
return (0);
}
if ((flags & USTR_FLAG_PARSE_NUM_NO_BEG_ZERO) && (**ptr == '0') && (*len > 1))
{
*ern = USTR_TYPE_PARSE_NUM_ERR_BEG_ZERO;
return (0);
}
return (base);
}
#if USTR_CONF_HAVE_STDINT_H
USTR_CONF_I_PROTO
#else
USTR_CONF_e_PROTO
USTR__UMAX ustr_parse_uintmaxx(const struct Ustr *, size_t, unsigned int,
USTR__UMAX, USTR__UMAX, char,
size_t *, unsigned int *)
USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_L((1));
USTR_CONF_i_PROTO
#endif
USTR__UMAX ustr_parse_uintmaxx(const struct Ustr *s1, size_t off,
unsigned int flags,
USTR__UMAX num_min, USTR__UMAX num_max,
const char *sep,
size_t *ret_len, unsigned int *ern)
{
static const char local_let_low[] = "abcdefghijklmnopqrstuvwxyz";
static const char local_let_high[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
unsigned int dummy_ern;
unsigned int num_base = 0;
int tst_neg = USTR_FALSE;
int tst_0 = USTR_FALSE;
int done_once = USTR_FALSE;
char num_end = '9';
const char *ptr = ustr_cstr(s1);
size_t len = ustr_len(s1);
size_t orig_len;
USTR__UMAX ret = 0;
size_t slen = strlen(sep);
USTR_ASSERT(ustr_assert_valid(s1));
USTR_ASSERT(!(flags & USTR_FLAG_PARSE_NUM_NO_NEGATIVE) || !num_min);
if (!ern) ern = &dummy_ern;
*ern = USTR_TYPE_PARSE_NUM_ERR_NONE;
USTR_ASSERT_RET(off <= len, 0);
ptr += off;
len -= off;
orig_len = len;
if (!(num_base = ustr__parse_num_beg(&ptr,&len, flags, &tst_neg,&tst_0, ern)))
return (0);
if (tst_neg && (flags & USTR_FLAG_PARSE_NUM_NO_NEGATIVE))
{
*ern = USTR_TYPE_PARSE_NUM_ERR_NEGATIVE;
return (0);
}
if (num_base < 10)
num_end = '0' + num_base - 1;
if (tst_neg)
num_max = num_min;
done_once = tst_0;
while (len)
{
const char *end = 0;
unsigned int add_num = 0;
USTR__UMAX old_ret = ret;
if (done_once && (flags & USTR_FLAG_PARSE_NUM_SEP) &&
(*ptr == *sep) && (len >= slen) && !memcmp(ptr, sep, slen))
{
ptr += slen;
len -= slen;
continue;
}
else
{
if ((*ptr >= '0') && (*ptr <= num_end))
add_num = (*ptr - '0');
else if (num_base <= 10)
break;
else if ((end = memchr(local_let_low, *ptr, num_base - 10)))
add_num = 10 + (end - local_let_low);
else if ((end = memchr(local_let_high, *ptr, num_base - 10)))
add_num = 10 + (end - local_let_high);
else
break;
}
ret = (ret * num_base) + add_num;
if ((flags & USTR_FLAG_PARSE_NUM_OVERFLOW) &&
(((ret - add_num) / num_base) != old_ret))
{
*ern = USTR_TYPE_PARSE_NUM_ERR_OVERFLOW;
ret = 0;
break;
}
++ptr;
--len;
done_once = USTR_TRUE;
}
if (!done_once)
{
*ern = USTR_TYPE_PARSE_NUM_ERR_OOB;
return (0);
}
if (!*ern && (flags & USTR_FLAG_PARSE_NUM_EXACT) && len)
*ern = USTR_TYPE_PARSE_NUM_ERR_OOB;
if (ret > num_max)
{
ret = num_max;
if (flags & USTR_FLAG_PARSE_NUM_OVERFLOW)
{
if (!*ern)
*ern = USTR_TYPE_PARSE_NUM_ERR_OVERFLOW;
ret = 0;
}
}
if (ret_len)
*ret_len = orig_len - len;
if (tst_neg)
return (-ret);
return (ret);
}
#if USTR_CONF_HAVE_STDINT_H
USTR_CONF_I_PROTO
uintmax_t ustr_parse_uintmax(const struct Ustr *s1, size_t off,
unsigned int flags, size_t *len, unsigned int *ern)
{
ustr_assert(!(flags & USTR_FLAG_PARSE_NUM_NO_NEGATIVE));
flags |= USTR_FLAG_PARSE_NUM_NO_NEGATIVE;
return (ustr_parse_uintmaxx(s1, off, flags, 0, UINTMAX_MAX, "_", len, ern));
}
USTR_CONF_I_PROTO
intmax_t ustr_parse_intmax(const struct Ustr *s1, size_t off,
unsigned int flags, size_t *len, unsigned int *ern)
{
uintmax_t num_min = INTMAX_MIN;
ustr_assert(!(flags & USTR_FLAG_PARSE_NUM_NO_NEGATIVE));
return (ustr_parse_uintmaxx(s1,off, flags, -num_min,INTMAX_MAX, "_",len,ern));
}
#endif
USTR_CONF_I_PROTO
unsigned long ustr_parse_ulongx(const struct Ustr *s1, size_t off,
unsigned int flags,
unsigned long num_min, unsigned long num_max,
const char *sep, size_t *len, unsigned int *ern)
{ return (ustr_parse_uintmaxx(s1,off, flags, num_min,num_max, sep, len, ern)); }
USTR_CONF_I_PROTO
unsigned long ustr_parse_ulong(const struct Ustr *s1, size_t off,
unsigned int flags,
size_t *len, unsigned int *ern)
{
ustr_assert(!(flags & USTR_FLAG_PARSE_NUM_NO_NEGATIVE));
flags |= USTR_FLAG_PARSE_NUM_NO_NEGATIVE;
return (ustr_parse_uintmaxx(s1, off, flags, 0, ULONG_MAX, "_", len, ern));
}
USTR_CONF_I_PROTO
long ustr_parse_long(const struct Ustr *s1, size_t off, unsigned int flags,
size_t *len, unsigned int *ern)
{
unsigned long num_min = LONG_MIN;
ustr_assert(!(flags & USTR_FLAG_PARSE_NUM_NO_NEGATIVE));
return (ustr_parse_uintmaxx(s1,off, flags, -num_min, LONG_MAX, "_", len,ern));
}
USTR_CONF_I_PROTO
unsigned int ustr_parse_uint(const struct Ustr *s1, size_t off,
unsigned int flags, size_t *len, unsigned int *ern)
{
ustr_assert(!(flags & USTR_FLAG_PARSE_NUM_NO_NEGATIVE));
flags |= USTR_FLAG_PARSE_NUM_NO_NEGATIVE;
return (ustr_parse_uintmaxx(s1, off, flags, 0, UINT_MAX, "_", len, ern));
}
USTR_CONF_I_PROTO
int ustr_parse_int(const struct Ustr *s1, size_t off, unsigned int flags,
size_t *len, unsigned int *ern)
{
unsigned int num_min = INT_MIN;
ustr_assert(!(flags & USTR_FLAG_PARSE_NUM_NO_NEGATIVE));
return (ustr_parse_uintmaxx(s1,off, flags, -num_min, INT_MAX, "_", len, ern));
}
USTR_CONF_I_PROTO
unsigned short ustr_parse_ushort(const struct Ustr *s1, size_t off,
unsigned int flags,
size_t *len, unsigned int *ern)
{
ustr_assert(!(flags & USTR_FLAG_PARSE_NUM_NO_NEGATIVE));
flags |= USTR_FLAG_PARSE_NUM_NO_NEGATIVE;
return (ustr_parse_uintmaxx(s1, off, flags, 0, USHRT_MAX, "_", len, ern));
}
USTR_CONF_I_PROTO
short ustr_parse_short(const struct Ustr *s1, size_t off, unsigned int flags,
size_t *len, unsigned int *ern)
{
unsigned short num_min = SHRT_MIN;
ustr_assert(!(flags & USTR_FLAG_PARSE_NUM_NO_NEGATIVE));
return (ustr_parse_uintmaxx(s1,off, flags, -num_min, SHRT_MAX, "_", len,ern));
}