#include "strparse.h"
#ifndef WITHOUT_LIBCURL
#include <curl/curl.h>
#endif
void curlx_str_init(struct Curl_str *out)
{
out->str = NULL;
out->len = 0;
}
void curlx_str_assign(struct Curl_str *out, const char *str, size_t len)
{
out->str = str;
out->len = len;
}
int curlx_str_until(const char **linep, struct Curl_str *out,
const size_t max, char delim)
{
const char *s = *linep;
size_t len = 0;
DEBUGASSERT(linep && *linep && out && max && delim);
curlx_str_init(out);
while(*s && (*s != delim)) {
s++;
if(++len > max) {
return STRE_BIG;
}
}
if(!len)
return STRE_SHORT;
out->str = *linep;
out->len = len;
*linep = s;
return STRE_OK;
}
int curlx_str_word(const char **linep, struct Curl_str *out,
const size_t max)
{
return curlx_str_until(linep, out, max, ' ');
}
int curlx_str_untilnl(const char **linep, struct Curl_str *out,
const size_t max)
{
const char *s = *linep;
size_t len = 0;
DEBUGASSERT(linep && *linep && out && max);
curlx_str_init(out);
while(*s && !ISNEWLINE(*s)) {
s++;
if(++len > max)
return STRE_BIG;
}
if(!len)
return STRE_SHORT;
out->str = *linep;
out->len = len;
*linep = s;
return STRE_OK;
}
int curlx_str_quotedword(const char **linep, struct Curl_str *out,
const size_t max)
{
const char *s = *linep;
size_t len = 0;
DEBUGASSERT(linep && *linep && out && max);
curlx_str_init(out);
if(*s != '\"')
return STRE_BEGQUOTE;
s++;
while(*s && (*s != '\"')) {
s++;
if(++len > max)
return STRE_BIG;
}
if(*s != '\"')
return STRE_ENDQUOTE;
out->str = (*linep) + 1;
out->len = len;
*linep = s + 1;
return STRE_OK;
}
int curlx_str_single(const char **linep, char byte)
{
DEBUGASSERT(linep && *linep);
if(**linep != byte)
return STRE_BYTE;
(*linep)++;
return STRE_OK;
}
int curlx_str_singlespace(const char **linep)
{
return curlx_str_single(linep, ' ');
}
#define valid_digit(x,m) \
(((x) >= '0') && ((x) <= m) && Curl_hexasciitable[(x)-'0'])
const unsigned char Curl_hexasciitable[] = {
16, 1, 2, 3, 4, 5, 6, 7, 8, 9,
0, 0, 0, 0, 0, 0, 0,
10, 11, 12, 13, 14, 15,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10, 11, 12, 13, 14, 15
};
static int str_num_base(const char **linep, curl_off_t *nump, curl_off_t max,
int base)
{
curl_off_t num = 0;
const char *p;
int m = (base == 10) ? '9' :
(base == 16) ? 'f' : '7';
DEBUGASSERT(linep && *linep && nump);
DEBUGASSERT((base == 8) || (base == 10) || (base == 16));
DEBUGASSERT(max >= 0);
*nump = 0;
p = *linep;
if(!valid_digit(*p, m))
return STRE_NO_NUM;
if(max < base) {
do {
int n = Curl_hexval(*p++);
num = num * base + n;
if(num > max)
return STRE_OVERFLOW;
} while(valid_digit(*p, m));
}
else {
do {
int n = Curl_hexval(*p++);
if(num > ((max - n) / base))
return STRE_OVERFLOW;
num = num * base + n;
} while(valid_digit(*p, m));
}
*nump = num;
*linep = p;
return STRE_OK;
}
int curlx_str_number(const char **linep, curl_off_t *nump, curl_off_t max)
{
return str_num_base(linep, nump, max, 10);
}
int curlx_str_hex(const char **linep, curl_off_t *nump, curl_off_t max)
{
return str_num_base(linep, nump, max, 16);
}
int curlx_str_octal(const char **linep, curl_off_t *nump, curl_off_t max)
{
return str_num_base(linep, nump, max, 8);
}
int curlx_str_numblanks(const char **str, curl_off_t *num)
{
curlx_str_passblanks(str);
return curlx_str_number(str, num, CURL_OFF_T_MAX);
}
int curlx_str_newline(const char **linep)
{
DEBUGASSERT(linep && *linep);
if(ISNEWLINE(**linep)) {
(*linep)++;
return STRE_OK;
}
return STRE_NEWLINE;
}
#ifndef WITHOUT_LIBCURL
int curlx_str_casecompare(struct Curl_str *str, const char *check)
{
size_t clen = check ? strlen(check) : 0;
return ((str->len == clen) && curl_strnequal(str->str, check, clen));
}
#endif
int curlx_str_cmp(struct Curl_str *str, const char *check)
{
if(check) {
size_t clen = strlen(check);
return ((str->len == clen) && !strncmp(str->str, check, clen));
}
return !!(str->len);
}
int curlx_str_nudge(struct Curl_str *str, size_t num)
{
if(num <= str->len) {
str->str += num;
str->len -= num;
return STRE_OK;
}
return STRE_OVERFLOW;
}
int curlx_str_cspn(const char **linep, struct Curl_str *out,
const char *reject)
{
const char *s = *linep;
size_t len;
DEBUGASSERT(linep && *linep);
len = strcspn(s, reject);
if(len) {
out->str = s;
out->len = len;
*linep = &s[len];
return STRE_OK;
}
curlx_str_init(out);
return STRE_SHORT;
}
void curlx_str_trimblanks(struct Curl_str *out)
{
while(out->len && ISBLANK(*out->str))
curlx_str_nudge(out, 1);
while(out->len && ISBLANK(out->str[out->len - 1]))
out->len--;
}
void curlx_str_passblanks(const char **linep)
{
while(ISBLANK(**linep))
(*linep)++;
}