Skip to content

Commit

Permalink
rewrote zsetstr in terms of psetstr
Browse files Browse the repository at this point in the history
  • Loading branch information
suiginsoft committed Feb 28, 2017
1 parent 009b268 commit 03f3679
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 93 deletions.
4 changes: 2 additions & 2 deletions check/z/getset.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ int main(int argc, char *argv[])
assert(hebi_zgetstr(buf, sizeof(buf), a, 10, 0) < sizeof(buf));
assert(strcmp(buf, s0) == 0);

assert(hebi_zsetstr(a, s1, NULL, 10, 0) > 0);
assert(hebi_zsetstr(a, s1, NULL, 10, 0));
assert(hebi_zsign(a) > 0);
assert(hebi_zused(a) == 2);
assert(hebi_zeven(a));
Expand All @@ -102,7 +102,7 @@ int main(int argc, char *argv[])
assert(hebi_zgetstr(buf, sizeof(buf), a, 10, 0) < sizeof(buf));
assert(strcmp(buf, s1) == 0);

assert(hebi_zsetstr(a, s2, NULL, 0, 0) > 0);
assert(hebi_zsetstr(a, s2, NULL, 0, 0));
assert(hebi_zsign(a) < 0);
assert(hebi_zused(a) == 6);
assert(!hebi_zeven(a));
Expand Down
4 changes: 2 additions & 2 deletions hebimath.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -185,10 +185,10 @@ struct hebi_psetstrstate
size_t hm_start;
size_t hm_end;
size_t hm_cur;
struct hebi_error hm_error;
unsigned int hm_alphabet;
unsigned int hm_radix;
int hm_sign;
int hm_errcode;
};

struct hebi_kiss {
Expand Down Expand Up @@ -339,7 +339,7 @@ HEBI_API int64_t hebi_zgetsi(hebi_zsrcptr a__);
HEBI_API uint64_t hebi_zgetsu(hebi_zsrcptr a__);
HEBI_API size_t hebi_zgetstr(char *HEBI_RESTRICT str__, size_t len__, hebi_zsrcptr HEBI_RESTRICT a__, unsigned int base__, unsigned int flags__);
HEBI_API size_t hebi_zgetstrlen(hebi_zsrcptr a__, unsigned int base__, unsigned int flags__);
HEBI_API size_t hebi_zsetstr(hebi_zptr HEBI_RESTRICT r__, const char *HEBI_RESTRICT str__, char **HEBI_RESTRICT strptr__, unsigned int base__, unsigned int flags__);
HEBI_API int hebi_zsetstr(hebi_zptr HEBI_RESTRICT r__, const char *HEBI_RESTRICT str__, char **HEBI_RESTRICT strptr__, unsigned int base__, unsigned int flags__);
HEBI_API int hebi_zcmp(hebi_zsrcptr a__, hebi_zsrcptr b__);
HEBI_API int hebi_zcmpmag(hebi_zsrcptr a__, hebi_zsrcptr b__);
HEBI_API int hebi_zcmpi(hebi_zsrcptr a__, int64_t b__);
Expand Down
34 changes: 16 additions & 18 deletions src/p/psetstr.c
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,7 @@ static size_t
error(struct hebi_psetstrstate *state, size_t cur, int code)
{
state->hm_cur = cur;
state->hm_error.he_code = code;
state->hm_errcode = code;
return SIZE_MAX;
}

Expand Down Expand Up @@ -504,7 +504,7 @@ outofspace(struct hebi_psetstrstate *state, size_t cur, size_t sizethusfar)
size_t space;

state->hm_cur = cur;
state->hm_error.he_code = HEBI_EBADLENGTH;
state->hm_errcode = HEBI_EBADLENGTH;

space = estimatespace(cur, state->hm_end, state->hm_radix);
if (UNLIKELY(space + sizethusfar < sizethusfar))
Expand Down Expand Up @@ -570,14 +570,14 @@ hebi_psetstr(
radix = state->hm_radix;
ASSERT(radix <= decoder->maxradix);

ASSERT(state->hm_errcode == HEBI_ENONE);
state->hm_errcode = HEBI_ENONE;

/* setup to start reading digits */
size = 0;
digitlut = decoder->digitlut;
maxdigits = maxdigitslut[radix - 1];

state->hm_error.he_domain = HEBI_ERRDOM_HEBI;
state->hm_error.he_code = HEBI_ENONE;

/*
* check if base if power of two and use bit-shifting to accumulate
* the result if this is the case, otherwise use multiplication
Expand Down Expand Up @@ -673,10 +673,9 @@ hebi_psetstrprepare(
state->hm_len = len;
state->hm_start = cur;
state->hm_end = end;
state->hm_error.he_domain = HEBI_ERRDOM_HEBI;
state->hm_error.he_code = HEBI_ENONE;
state->hm_radix = 0;
state->hm_sign = 0;
state->hm_sign = 1;
state->hm_errcode = HEBI_ENONE;

/* determine alphabet index and make sure it's valid */
state->hm_alphabet = flags & HEBI_STR_ALPHABET_MASK;
Expand Down Expand Up @@ -705,21 +704,20 @@ hebi_psetstrprepare(
if (UNLIKELY(radix < 2 || decoder->maxradix < radix))
return error(state, cur, HEBI_EBADVALUE);

/* treat zero length digit sequence as syntax error */
/* consume leading zero characters and estimate remaining space */
if (UNLIKELY(cur >= end))
return error(state, cur, HEBI_EBADSYNTAX);

/* consume leading zero characters and estimate remaining space */
while (cur < end && str[cur] == decoder->zero)
cur++;
state->hm_cur = cur;

/* determine packet space estimate for remaining digits */
if (LIKELY(cur < end)) {
space = estimatespace(cur, end, radix);
if (UNLIKELY(space >= HEBI_PACKET_MAXLEN))
return error(state, cur, HEBI_EBADLENGTH);
return space + 1;
if (UNLIKELY(cur >= end)) {
state->hm_sign = 0;
return 0;
}
return 0;

space = estimatespace(cur, end, radix);
if (UNLIKELY(space >= HEBI_PACKET_MAXLEN))
return error(state, cur, HEBI_EBADLENGTH);
return space + 1;
}
101 changes: 30 additions & 71 deletions src/z/zsetstr.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,89 +4,48 @@
*/

#include "../../internal.h"
#include <ctype.h>
#include <string.h>

enum { FLAGS = HEBI_STR_RADIX | HEBI_STR_SIGN | HEBI_STR_TRIM };

HEBI_API
size_t
int
hebi_zsetstr(
hebi_zptr restrict r,
const char *restrict str,
char **restrict endptr,
unsigned int base,
unsigned int flags )
{
IGNORE(flags);

const char *ptr;
const char *startptr;
unsigned int digit;
unsigned int digit_range;
unsigned int letter_range;
int neg;

if (UNLIKELY(base && (base < 2 || 36 < base)))
hebi_error_raise(HEBI_ERRDOM_HEBI, HEBI_EBADVALUE);

/* skip whitespace */
ptr = str;
while (isspace(*ptr))
++ptr;

/* determine sign */
neg = 0;
if (*ptr == '-') {
neg = 1;
++ptr;
} else if (*ptr == '+') {
++ptr;
}

/* determine base and skip base prefix */
if (base == 0) {
base = 10;
if (ptr[0] == '0') {
base -= 2;
if (ptr[1] == 'x' || ptr[1] == 'X') {
base <<= 1;
ptr += 2;
}
}
} else if (base == 16 && ptr[0] == '0' &&
(ptr[1] == 'x' || ptr[1] == 'X')) {
ptr += 2;
struct hebi_psetstrstate state;
size_t len;
size_t space;
size_t used;

len = strlen(str);
space = hebi_psetstrprepare(&state, str, len, base, flags | FLAGS);

if (UNLIKELY(space == SIZE_MAX)) {
used = SIZE_MAX;
} else if (space > 0) {
hebi_zgrow__(r, space);
used = hebi_psetstr(r->hz_packs, space, &state);
} else {
used = 0;
}

/* determine allowed character ranges for base */
digit_range = base;
letter_range = 0;
if (base > 10) {
digit_range = 10;
letter_range = base - 10;
}

/* read in the digits and accumulate result */
hebi_zsetzero(r);
for (startptr = ptr; ; ++ptr) {
digit = (unsigned int)*ptr - '0';
if (digit >= digit_range) {
digit = ((unsigned int)*ptr & 0xDF) - 'A';
if (digit >= letter_range)
break;
digit += 10;
}
hebi_zmulu(r, r, base);
hebi_zaddu(r, r, digit);
}

/* finalize result */
if (UNLIKELY(ptr <= startptr))
ptr = str;

if (endptr)
*endptr = (char *)ptr;
*endptr = (char *)str + state.hm_cur;

if (neg)
hebi_zneg(r, r);
if (UNLIKELY(used == SIZE_MAX)) {
hebi_zsetzero(r);
if (state.hm_errcode != HEBI_EBADSYNTAX)
hebi_error_raise(HEBI_ERRDOM_HEBI, state.hm_errcode);
return 0;
}

return (size_t)(ptr - str);
ASSERT(used <= space);
r->hz_used = used;
r->hz_sign = state.hm_sign;
return 1;
}

0 comments on commit 03f3679

Please sign in to comment.