added some http processing code
This commit is contained in:
parent
a2f0fa9c7f
commit
49ad401433
@ -27,6 +27,7 @@ include_HEADERS = \
|
|||||||
mio-ecs.h \
|
mio-ecs.h \
|
||||||
mio-fmt.h \
|
mio-fmt.h \
|
||||||
mio-htb.h \
|
mio-htb.h \
|
||||||
|
mio-htrd.h \
|
||||||
mio-htre.h \
|
mio-htre.h \
|
||||||
mio-http.h \
|
mio-http.h \
|
||||||
mio-nwif.h \
|
mio-nwif.h \
|
||||||
|
@ -407,6 +407,7 @@ include_HEADERS = \
|
|||||||
mio-ecs.h \
|
mio-ecs.h \
|
||||||
mio-fmt.h \
|
mio-fmt.h \
|
||||||
mio-htb.h \
|
mio-htb.h \
|
||||||
|
mio-htrd.h \
|
||||||
mio-htre.h \
|
mio-htre.h \
|
||||||
mio-http.h \
|
mio-http.h \
|
||||||
mio-nwif.h \
|
mio-nwif.h \
|
||||||
|
121
mio/lib/htrd.c
121
mio/lib/htrd.c
@ -22,10 +22,9 @@
|
|||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <mio/http/htrd.h>
|
#include "mio-htrd.h"
|
||||||
#include <mio/cmn/chr.h>
|
#include "mio-chr.h"
|
||||||
#include <mio/cmn/path.h>
|
#include "mio-prv.h"
|
||||||
#include "../cmn/mem-prv.h"
|
|
||||||
|
|
||||||
static const mio_bch_t NUL = '\0';
|
static const mio_bch_t NUL = '\0';
|
||||||
|
|
||||||
@ -78,19 +77,17 @@ static MIO_INLINE int is_xdigit_octet (mio_bch_t c)
|
|||||||
|
|
||||||
static MIO_INLINE int digit_to_num (mio_bch_t c)
|
static MIO_INLINE int digit_to_num (mio_bch_t c)
|
||||||
{
|
{
|
||||||
if (c >= '0' && c <= '9') return c - '0';
|
return MIO_DIGIT_TO_NUM(c);
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static MIO_INLINE int xdigit_to_num (mio_bch_t c)
|
static MIO_INLINE int xdigit_to_num (mio_bch_t c)
|
||||||
{
|
{
|
||||||
return MIO_MXDIGITTONUM (c);
|
return MIO_XDIGIT_TO_NUM(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static MIO_INLINE int push_to_buffer (mio_htrd_t* htrd, mio_htob_t* octb, const mio_bch_t* ptr, mio_oow_t len)
|
static MIO_INLINE int push_to_buffer (mio_htrd_t* htrd, mio_htob_t* octb, const mio_bch_t* ptr, mio_oow_t len)
|
||||||
{
|
{
|
||||||
if (mio_mbs_ncat (octb, ptr, len) == (mio_oow_t)-1)
|
if (mio_becs_ncat (octb, ptr, len) == (mio_oow_t)-1)
|
||||||
{
|
{
|
||||||
htrd->errnum = MIO_HTRD_ENOMEM;
|
htrd->errnum = MIO_HTRD_ENOMEM;
|
||||||
return -1;
|
return -1;
|
||||||
@ -100,7 +97,7 @@ static MIO_INLINE int push_to_buffer (mio_htrd_t* htrd, mio_htob_t* octb, const
|
|||||||
|
|
||||||
static MIO_INLINE int push_content (mio_htrd_t* htrd, const mio_bch_t* ptr, mio_oow_t len)
|
static MIO_INLINE int push_content (mio_htrd_t* htrd, const mio_bch_t* ptr, mio_oow_t len)
|
||||||
{
|
{
|
||||||
MIO_ASSERT (len > 0);
|
MIO_ASSERT (htrd->mio, len > 0);
|
||||||
|
|
||||||
if (mio_htre_addcontent(&htrd->re, ptr, len) <= -1)
|
if (mio_htre_addcontent(&htrd->re, ptr, len) <= -1)
|
||||||
{
|
{
|
||||||
@ -120,8 +117,8 @@ static MIO_INLINE void clear_feed (mio_htrd_t* htrd)
|
|||||||
htrd->clean = 1;
|
htrd->clean = 1;
|
||||||
mio_htre_clear (&htrd->re);
|
mio_htre_clear (&htrd->re);
|
||||||
|
|
||||||
mio_mbs_clear (&htrd->fed.b.tra);
|
mio_becs_clear (&htrd->fed.b.tra);
|
||||||
mio_mbs_clear (&htrd->fed.b.raw);
|
mio_becs_clear (&htrd->fed.b.raw);
|
||||||
|
|
||||||
MIO_MEMSET (&htrd->fed.s, 0, MIO_SIZEOF(htrd->fed.s));
|
MIO_MEMSET (&htrd->fed.s, 0, MIO_SIZEOF(htrd->fed.s));
|
||||||
}
|
}
|
||||||
@ -138,7 +135,7 @@ mio_htrd_t* mio_htrd_open (mio_t* mio, mio_oow_t xtnsize)
|
|||||||
mio_freemem (mio, htrd);
|
mio_freemem (mio, htrd);
|
||||||
return MIO_NULL;
|
return MIO_NULL;
|
||||||
}
|
}
|
||||||
else MIO_MEMSET (MIO_XTN(htrd), 0, xtnsize);
|
else MIO_MEMSET (htrd + 1, 0, xtnsize);
|
||||||
}
|
}
|
||||||
return htrd;
|
return htrd;
|
||||||
}
|
}
|
||||||
@ -179,17 +176,17 @@ void mio_htrd_fini (mio_htrd_t* htrd)
|
|||||||
{
|
{
|
||||||
mio_htre_fini (&htrd->re);
|
mio_htre_fini (&htrd->re);
|
||||||
|
|
||||||
mio_mbs_fini (&htrd->fed.b.tra);
|
mio_becs_fini (&htrd->fed.b.tra);
|
||||||
mio_mbs_fini (&htrd->fed.b.raw);
|
mio_becs_fini (&htrd->fed.b.raw);
|
||||||
#if 0
|
#if 0
|
||||||
mio_mbs_fini (&htrd->tmp.qparam);
|
mio_becs_fini (&htrd->tmp.qparam);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static mio_bch_t* parse_initial_line (mio_htrd_t* htrd, mio_bch_t* line)
|
static mio_bch_t* parse_initial_line (mio_htrd_t* htrd, mio_bch_t* line)
|
||||||
{
|
{
|
||||||
mio_bch_t* p = line;
|
mio_bch_t* p = line;
|
||||||
mio_mcstr_t tmp;
|
mio_bcs_t tmp;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* ignore leading spaces excluding crlf */
|
/* ignore leading spaces excluding crlf */
|
||||||
@ -212,11 +209,10 @@ static mio_bch_t* parse_initial_line (mio_htrd_t* htrd, mio_bch_t* line)
|
|||||||
|
|
||||||
*p = '\0'; /* null-terminate the method name */
|
*p = '\0'; /* null-terminate the method name */
|
||||||
|
|
||||||
htrd->re.u.q.method.type = mio_mcstrtohttpmethod (&tmp);
|
htrd->re.u.q.method.type = mio_bchars_to_http_method(tmp.ptr, tmp.len);
|
||||||
htrd->re.u.q.method.name = tmp.ptr;
|
htrd->re.u.q.method.name = tmp.ptr;
|
||||||
}
|
}
|
||||||
else if ((htrd->option & MIO_HTRD_RESPONSE) &&
|
else if ((htrd->option & MIO_HTRD_RESPONSE) && mio_comp_bchars_bcstr(tmp.ptr, tmp.len, "HTTP", 1) == 0)
|
||||||
mio_mbsxcmp (tmp.ptr, tmp.len, "HTTP") == 0)
|
|
||||||
{
|
{
|
||||||
/* it begins with HTTP. it may be a response */
|
/* it begins with HTTP. it may be a response */
|
||||||
htrd->re.type = MIO_HTRE_S;
|
htrd->re.type = MIO_HTRE_S;
|
||||||
@ -296,7 +292,7 @@ static mio_bch_t* parse_initial_line (mio_htrd_t* htrd, mio_bch_t* line)
|
|||||||
#if 0
|
#if 0
|
||||||
mio_bch_t* out;
|
mio_bch_t* out;
|
||||||
#endif
|
#endif
|
||||||
mio_mcstr_t param;
|
mio_bcs_t param;
|
||||||
|
|
||||||
/* skip spaces */
|
/* skip spaces */
|
||||||
do p++; while (is_space_octet(*p));
|
do p++; while (is_space_octet(*p));
|
||||||
@ -412,16 +408,16 @@ static mio_bch_t* parse_initial_line (mio_htrd_t* htrd, mio_bch_t* line)
|
|||||||
/* if the url begins with xxx://,
|
/* if the url begins with xxx://,
|
||||||
* skip xxx:/ and canonicalize from the second slash */
|
* skip xxx:/ and canonicalize from the second slash */
|
||||||
while (is_alpha_octet(*qpath)) qpath++;
|
while (is_alpha_octet(*qpath)) qpath++;
|
||||||
if (mio_mbszcmp (qpath, "://", 3) == 0)
|
if (mio_comp_bcstr_limited(qpath, "://", 3, 1) == 0)
|
||||||
{
|
{
|
||||||
qpath = qpath + 2; /* set the position to the second / in :// */
|
qpath = qpath + 2; /* set the position to the second / in :// */
|
||||||
htrd->re.u.q.path.len = mio_canonmbspath (qpath, qpath, 0);
|
htrd->re.u.q.path.len = mio_canon_bcstr_path(qpath, qpath, 0);
|
||||||
htrd->re.u.q.path.len += qpath - htrd->re.u.q.path.ptr;
|
htrd->re.u.q.path.len += qpath - htrd->re.u.q.path.ptr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
qpath = htrd->re.u.q.path.ptr;
|
qpath = htrd->re.u.q.path.ptr;
|
||||||
htrd->re.u.q.path.len = mio_canonmbspath (qpath, qpath, 0);
|
htrd->re.u.q.path.len = mio_canon_bcstr_path(qpath, qpath, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -481,12 +477,6 @@ void mio_htrd_clear (mio_htrd_t* htrd)
|
|||||||
htrd->flags = 0;
|
htrd->flags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* mio_htrd_getxtn (mio_htrd_t* htrd)
|
|
||||||
{
|
|
||||||
return MIO_XTN (htrd);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
mio_htrd_errnum_t mio_htrd_geterrnum (mio_htrd_t* htrd)
|
mio_htrd_errnum_t mio_htrd_geterrnum (mio_htrd_t* htrd)
|
||||||
{
|
{
|
||||||
return htrd->errnum;
|
return htrd->errnum;
|
||||||
@ -520,15 +510,15 @@ static int capture_connection (mio_htrd_t* htrd, mio_htb_pair_t* pair)
|
|||||||
while (val->next) val = val->next;
|
while (val->next) val = val->next;
|
||||||
|
|
||||||
/* The value for Connection: may get comma-separated.
|
/* The value for Connection: may get comma-separated.
|
||||||
* so use mio_mbscaseword() instead of mio_mbscmp(). */
|
* so use mio_find_bcstr_word_in_bcstr() instead of mio_comp_bcstr(). */
|
||||||
|
|
||||||
if (mio_mbscaseword (val->ptr, "close", ','))
|
if (mio_find_bcstr_word_in_bcstr(val->ptr, "close", ',', 1))
|
||||||
{
|
{
|
||||||
htrd->re.flags &= ~MIO_HTRE_ATTR_KEEPALIVE;
|
htrd->re.flags &= ~MIO_HTRE_ATTR_KEEPALIVE;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mio_mbscaseword (val->ptr, "keep-alive", ','))
|
if (mio_find_bcstr_word_in_bcstr(val->ptr, "keep-alive", ',', 1))
|
||||||
{
|
{
|
||||||
htrd->re.flags |= MIO_HTRE_ATTR_KEEPALIVE;
|
htrd->re.flags |= MIO_HTRE_ATTR_KEEPALIVE;
|
||||||
return 0;
|
return 0;
|
||||||
@ -543,8 +533,7 @@ static int capture_connection (mio_htrd_t* htrd, mio_htb_pair_t* pair)
|
|||||||
* For the second Keep-Alive, this function sees 'Keep-Alive,Keep-Alive'
|
* For the second Keep-Alive, this function sees 'Keep-Alive,Keep-Alive'
|
||||||
* That's because values of the same keys are concatenated.
|
* That's because values of the same keys are concatenated.
|
||||||
*/
|
*/
|
||||||
if (htrd->re.version.major < 1 ||
|
if (htrd->re.version.major < 1 || (htrd->re.version.major == 1 && htrd->re.version.minor <= 0))
|
||||||
(htrd->re.version.major == 1 && htrd->re.version.minor <= 0))
|
|
||||||
{
|
{
|
||||||
htrd->re.flags &= ~MIO_HTRE_ATTR_KEEPALIVE;
|
htrd->re.flags &= ~MIO_HTRE_ATTR_KEEPALIVE;
|
||||||
}
|
}
|
||||||
@ -615,7 +604,7 @@ static int capture_expect (mio_htrd_t* htrd, mio_htb_pair_t* pair)
|
|||||||
while (val)
|
while (val)
|
||||||
{
|
{
|
||||||
/* Expect: 100-continue is included */
|
/* Expect: 100-continue is included */
|
||||||
if (mio_mbscasecmp(val->ptr, "100-continue") == 0) htrd->re.flags |= MIO_HTRE_ATTR_EXPECT100;
|
if (mio_comp_bcstr(val->ptr, "100-continue", 1) == 0) htrd->re.flags |= MIO_HTRE_ATTR_EXPECT100;
|
||||||
val = val->next;
|
val = val->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -641,7 +630,7 @@ static int capture_transfer_encoding (mio_htrd_t* htrd, mio_htb_pair_t* pair)
|
|||||||
val = MIO_HTB_VPTR(pair);
|
val = MIO_HTB_VPTR(pair);
|
||||||
while (val->next) val = val->next;
|
while (val->next) val = val->next;
|
||||||
|
|
||||||
n = mio_mbscasecmp(val->ptr, "chunked");
|
n = mio_comp_bcstr(val->ptr, "chunked", 1);
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
{
|
{
|
||||||
/* if (htrd->re.attr.content_length > 0) */
|
/* if (htrd->re.attr.content_length > 0) */
|
||||||
@ -685,11 +674,7 @@ static MIO_INLINE int capture_key_header (mio_htrd_t* htrd, mio_htb_pair_t* pair
|
|||||||
{
|
{
|
||||||
mid = base + count / 2;
|
mid = base + count / 2;
|
||||||
|
|
||||||
n = mio_mbsxncasecmp (
|
n = mio_comp_bchars(MIO_HTB_KPTR(pair), MIO_HTB_KLEN(pair), hdrtab[mid].ptr, hdrtab[mid].len, 1);
|
||||||
MIO_HTB_KPTR(pair), MIO_HTB_KLEN(pair),
|
|
||||||
hdrtab[mid].ptr, hdrtab[mid].len
|
|
||||||
);
|
|
||||||
|
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
{
|
{
|
||||||
/* bingo! */
|
/* bingo! */
|
||||||
@ -723,7 +708,7 @@ static mio_htb_pair_t* hdr_cbserter (
|
|||||||
mio_htre_hdrval_t *val;
|
mio_htre_hdrval_t *val;
|
||||||
|
|
||||||
val = mio_allocmem(htb->mio, MIO_SIZEOF(*val));
|
val = mio_allocmem(htb->mio, MIO_SIZEOF(*val));
|
||||||
if (HAWK_UNLIKELY(!val))
|
if (MIO_UNLIKELY(!val))
|
||||||
{
|
{
|
||||||
tx->htrd->errnum = MIO_HTRD_ENOMEM;
|
tx->htrd->errnum = MIO_HTRD_ENOMEM;
|
||||||
return MIO_NULL;
|
return MIO_NULL;
|
||||||
@ -787,7 +772,7 @@ static mio_htb_pair_t* hdr_cbserter (
|
|||||||
mio_htre_hdrval_t* tmp;
|
mio_htre_hdrval_t* tmp;
|
||||||
|
|
||||||
val = (mio_htre_hdrval_t*)mio_allocmem(tx->htrd->mio, MIO_SIZEOF(*val));
|
val = (mio_htre_hdrval_t*)mio_allocmem(tx->htrd->mio, MIO_SIZEOF(*val));
|
||||||
if (HAWK_UNLIKELY(!val))
|
if (MIO_UNLIKELY(!val))
|
||||||
{
|
{
|
||||||
tx->htrd->errnum = MIO_HTRD_ENOMEM;
|
tx->htrd->errnum = MIO_HTRD_ENOMEM;
|
||||||
return MIO_NULL;
|
return MIO_NULL;
|
||||||
@ -800,7 +785,7 @@ static mio_htb_pair_t* hdr_cbserter (
|
|||||||
|
|
||||||
/* TODO: doubly linked list for speed-up??? */
|
/* TODO: doubly linked list for speed-up??? */
|
||||||
tmp = MIO_HTB_VPTR(pair);
|
tmp = MIO_HTB_VPTR(pair);
|
||||||
MIO_ASSERT (tmp != MIO_NULL);
|
MIO_ASSERT (tx->htrd->mio, tmp != MIO_NULL);
|
||||||
|
|
||||||
/* find the tail */
|
/* find the tail */
|
||||||
while (tmp->next) tmp = tmp->next;
|
while (tmp->next) tmp = tmp->next;
|
||||||
@ -826,7 +811,7 @@ mio_bch_t* parse_header_field (mio_htrd_t* htrd, mio_bch_t* line, mio_htb_t* tab
|
|||||||
while (is_space_octet(*p)) p++;
|
while (is_space_octet(*p)) p++;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
MIO_ASSERT (!is_whspace_octet(*p));
|
MIO_ASSERT (htrd->mio, !is_whspace_octet(*p));
|
||||||
|
|
||||||
/* check the field name */
|
/* check the field name */
|
||||||
name.ptr = last = p;
|
name.ptr = last = p;
|
||||||
@ -932,7 +917,7 @@ static MIO_INLINE int parse_initial_line_and_headers (
|
|||||||
/* add the terminating null for easier parsing */
|
/* add the terminating null for easier parsing */
|
||||||
if (push_to_buffer (htrd, &htrd->fed.b.raw, &NUL, 1) <= -1) return -1;
|
if (push_to_buffer (htrd, &htrd->fed.b.raw, &NUL, 1) <= -1) return -1;
|
||||||
|
|
||||||
p = MIO_MBS_PTR(&htrd->fed.b.raw);
|
p = MIO_BECS_PTR(&htrd->fed.b.raw);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
if (htrd->option & MIO_HTRD_SKIPEMPTYLINES)
|
if (htrd->option & MIO_HTRD_SKIPEMPTYLINES)
|
||||||
@ -941,7 +926,7 @@ static MIO_INLINE int parse_initial_line_and_headers (
|
|||||||
#endif
|
#endif
|
||||||
while (is_space_octet(*p)) p++;
|
while (is_space_octet(*p)) p++;
|
||||||
|
|
||||||
MIO_ASSERT (*p != '\0');
|
MIO_ASSERT (htrd->mio, *p != '\0');
|
||||||
|
|
||||||
/* parse the initial line */
|
/* parse the initial line */
|
||||||
if (!(htrd->option & MIO_HTRD_SKIPINITIALLINE))
|
if (!(htrd->option & MIO_HTRD_SKIPINITIALLINE))
|
||||||
@ -979,7 +964,7 @@ static const mio_bch_t* getchunklen (mio_htrd_t* htrd, const mio_bch_t* ptr, mio
|
|||||||
const mio_bch_t* end = ptr + len;
|
const mio_bch_t* end = ptr + len;
|
||||||
|
|
||||||
/* this function must be called in the GET_CHUNK_LEN context */
|
/* this function must be called in the GET_CHUNK_LEN context */
|
||||||
MIO_ASSERT (htrd->fed.s.chunk.phase == GET_CHUNK_LEN);
|
MIO_ASSERT (htrd->mio, htrd->fed.s.chunk.phase == GET_CHUNK_LEN);
|
||||||
|
|
||||||
if (htrd->fed.s.chunk.count <= 0)
|
if (htrd->fed.s.chunk.count <= 0)
|
||||||
{
|
{
|
||||||
@ -1063,7 +1048,7 @@ static const mio_bch_t* get_trailing_headers (
|
|||||||
{
|
{
|
||||||
mio_bch_t* p;
|
mio_bch_t* p;
|
||||||
|
|
||||||
MIO_ASSERT (htrd->fed.s.crlf <= 3);
|
MIO_ASSERT (htrd->mio, htrd->fed.s.crlf <= 3);
|
||||||
htrd->fed.s.crlf = 0;
|
htrd->fed.s.crlf = 0;
|
||||||
|
|
||||||
if (push_to_buffer (
|
if (push_to_buffer (
|
||||||
@ -1073,7 +1058,7 @@ static const mio_bch_t* get_trailing_headers (
|
|||||||
htrd, &htrd->fed.b.tra, &NUL, 1) <= -1)
|
htrd, &htrd->fed.b.tra, &NUL, 1) <= -1)
|
||||||
return MIO_NULL;
|
return MIO_NULL;
|
||||||
|
|
||||||
p = MIO_MBS_PTR(&htrd->fed.b.tra);
|
p = MIO_BECS_PTR(&htrd->fed.b.tra);
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@ -1123,7 +1108,7 @@ int mio_htrd_feed (mio_htrd_t* htrd, const mio_bch_t* req, mio_oow_t len)
|
|||||||
int header_completed_during_this_feed = 0;
|
int header_completed_during_this_feed = 0;
|
||||||
mio_oow_t avail;
|
mio_oow_t avail;
|
||||||
|
|
||||||
MIO_ASSERT (len > 0);
|
MIO_ASSERT (htrd->mio, len > 0);
|
||||||
|
|
||||||
if (htrd->flags & FEEDING_SUSPENDED)
|
if (htrd->flags & FEEDING_SUSPENDED)
|
||||||
{
|
{
|
||||||
@ -1212,7 +1197,7 @@ int mio_htrd_feed (mio_htrd_t* htrd, const mio_bch_t* req, mio_oow_t len)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* we got a complete request header. */
|
/* we got a complete request header. */
|
||||||
MIO_ASSERT (htrd->fed.s.crlf <= 3);
|
MIO_ASSERT (htrd->mio, htrd->fed.s.crlf <= 3);
|
||||||
|
|
||||||
/* reset the crlf state */
|
/* reset the crlf state */
|
||||||
htrd->fed.s.crlf = 0;
|
htrd->fed.s.crlf = 0;
|
||||||
@ -1260,7 +1245,7 @@ int mio_htrd_feed (mio_htrd_t* htrd, const mio_bch_t* req, mio_oow_t len)
|
|||||||
if (htrd->re.flags & MIO_HTRE_ATTR_CHUNKED)
|
if (htrd->re.flags & MIO_HTRE_ATTR_CHUNKED)
|
||||||
{
|
{
|
||||||
/* transfer-encoding: chunked */
|
/* transfer-encoding: chunked */
|
||||||
MIO_ASSERT (!(htrd->re.flags & MIO_HTRE_ATTR_LENGTH));
|
MIO_ASSERT (htrd->mio, !(htrd->re.flags & MIO_HTRE_ATTR_LENGTH));
|
||||||
|
|
||||||
dechunk_start:
|
dechunk_start:
|
||||||
htrd->fed.s.chunk.phase = GET_CHUNK_LEN;
|
htrd->fed.s.chunk.phase = GET_CHUNK_LEN;
|
||||||
@ -1411,7 +1396,7 @@ XXXXXXXX
|
|||||||
|
|
||||||
if (htrd->fed.s.chunk.phase == GET_CHUNK_DATA)
|
if (htrd->fed.s.chunk.phase == GET_CHUNK_DATA)
|
||||||
{
|
{
|
||||||
MIO_ASSERT (htrd->fed.s.need == 0);
|
MIO_ASSERT (htrd->mio, htrd->fed.s.need == 0);
|
||||||
htrd->fed.s.chunk.phase = GET_CHUNK_CRLF;
|
htrd->fed.s.chunk.phase = GET_CHUNK_CRLF;
|
||||||
|
|
||||||
dechunk_crlf:
|
dechunk_crlf:
|
||||||
@ -1495,8 +1480,8 @@ XXXXXXXX
|
|||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
mio_printf (MIO_T("CONTENT_LENGTH %d, RAW HEADER LENGTH %d\n"),
|
mio_printf (MIO_T("CONTENT_LENGTH %d, RAW HEADER LENGTH %d\n"),
|
||||||
(int)MIO_MBS_LEN(&htrd->re.content),
|
(int)MIO_BECS_LEN(&htrd->re.content),
|
||||||
(int)MIO_MBS_LEN(&htrd->fed.b.raw));
|
(int)MIO_BECS_LEN(&htrd->fed.b.raw));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
clear_feed (htrd);
|
clear_feed (htrd);
|
||||||
@ -1621,9 +1606,9 @@ void mio_htrd_undummify (mio_htrd_t* htrd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
int mio_htrd_scanqparam (mio_htrd_t* htrd, const mio_mcstr_t* cstr)
|
int mio_htrd_scanqparam (mio_htrd_t* htrd, const mio_bcs_t* cstr)
|
||||||
{
|
{
|
||||||
mio_mcstr_t key, val;
|
mio_bcs_t key, val;
|
||||||
const mio_bch_t* p, * end;
|
const mio_bch_t* p, * end;
|
||||||
mio_bch_t* out;
|
mio_bch_t* out;
|
||||||
|
|
||||||
@ -1637,11 +1622,11 @@ int mio_htrd_scanqparam (mio_htrd_t* htrd, const mio_mcstr_t* cstr)
|
|||||||
/* a key and a value pair including two terminating null
|
/* a key and a value pair including two terminating null
|
||||||
* can't exceed the the qparamstrlen + 2. only +1 below as there is
|
* can't exceed the the qparamstrlen + 2. only +1 below as there is
|
||||||
* one more space for an internal terminating null */
|
* one more space for an internal terminating null */
|
||||||
mio_mbs_setlen (&htrd->tmp.qparam, cstr->len + 1);
|
mio_becs_setlen (&htrd->tmp.qparam, cstr->len + 1);
|
||||||
|
|
||||||
/* let out point to the beginning of the qparam buffer.
|
/* let out point to the beginning of the qparam buffer.
|
||||||
* the loop below emits percent-decode key and value to this buffer. */
|
* the loop below emits percent-decode key and value to this buffer. */
|
||||||
out = MIO_MBS_PTR(&htrd->tmp.qparam);
|
out = MIO_BECS_PTR(&htrd->tmp.qparam);
|
||||||
|
|
||||||
key.ptr = out; key.len = 0;
|
key.ptr = out; key.len = 0;
|
||||||
val.ptr = MIO_NULL; val.len = 0;
|
val.ptr = MIO_NULL; val.len = 0;
|
||||||
@ -1650,7 +1635,7 @@ int mio_htrd_scanqparam (mio_htrd_t* htrd, const mio_mcstr_t* cstr)
|
|||||||
{
|
{
|
||||||
if (p >= end || *p == '&' || *p == ';')
|
if (p >= end || *p == '&' || *p == ';')
|
||||||
{
|
{
|
||||||
MIO_ASSERT (key.ptr != MIO_NULL);
|
MIO_ASSERT (htrd->mio, key.ptr != MIO_NULL);
|
||||||
|
|
||||||
*out++ = '\0';
|
*out++ = '\0';
|
||||||
if (val.ptr == MIO_NULL)
|
if (val.ptr == MIO_NULL)
|
||||||
@ -1664,13 +1649,11 @@ int mio_htrd_scanqparam (mio_htrd_t* htrd, const mio_mcstr_t* cstr)
|
|||||||
|
|
||||||
val.ptr = out;
|
val.ptr = out;
|
||||||
*out++ = '\0';
|
*out++ = '\0';
|
||||||
MIO_ASSERT (val.len == 0);
|
MIO_ASSERT (htrd->mio, val.len == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
MIO_ASSERTX (
|
/* set request parameter string callback before scanning */
|
||||||
htrd->recbs->qparamstr != MIO_NULL,
|
MIO_ASSERT (htrd->mio, htrd->recbs->qparamstr != MIO_NULL);
|
||||||
"set request parameter string callback before scanning"
|
|
||||||
);
|
|
||||||
|
|
||||||
htrd->errnum = MIO_HTRD_ENOERR;
|
htrd->errnum = MIO_HTRD_ENOERR;
|
||||||
if (htrd->recbs->qparamstr (htrd, &key, &val) <= -1)
|
if (htrd->recbs->qparamstr (htrd, &key, &val) <= -1)
|
||||||
@ -1684,7 +1667,7 @@ int mio_htrd_scanqparam (mio_htrd_t* htrd, const mio_mcstr_t* cstr)
|
|||||||
if (p >= end) break;
|
if (p >= end) break;
|
||||||
p++;
|
p++;
|
||||||
|
|
||||||
out = MIO_MBS_PTR(&htrd->tmp.qparam);
|
out = MIO_BECS_PTR(&htrd->tmp.qparam);
|
||||||
key.ptr = out; key.len = 0;
|
key.ptr = out; key.len = 0;
|
||||||
val.ptr = MIO_NULL; val.len = 0;
|
val.ptr = MIO_NULL; val.len = 0;
|
||||||
}
|
}
|
||||||
@ -1723,7 +1706,7 @@ int mio_htrd_scanqparam (mio_htrd_t* htrd, const mio_mcstr_t* cstr)
|
|||||||
}
|
}
|
||||||
while (1);
|
while (1);
|
||||||
|
|
||||||
mio_mbs_clear (&htrd->tmp.qparam);
|
mio_becs_clear (&htrd->tmp.qparam);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -395,11 +395,6 @@ mio_bch_t* mio_fmt_http_time_to_bcstr (const mio_ntime_t* nt, mio_bch_t* buf, mi
|
|||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define XDIGIT_TO_NUM(c) \
|
|
||||||
(((c) >= '0' && (c) <= '9')? ((c) - '0'): \
|
|
||||||
((c) >= 'A' && (c) <= 'F')? ((c) - 'A' + 10): \
|
|
||||||
((c) >= 'a' && (c) <= 'f')? ((c) - 'a' + 10): -1)
|
|
||||||
|
|
||||||
int mio_is_perenced_http_bcstr (const mio_bch_t* str)
|
int mio_is_perenced_http_bcstr (const mio_bch_t* str)
|
||||||
{
|
{
|
||||||
const mio_bch_t* p = str;
|
const mio_bch_t* p = str;
|
||||||
@ -408,11 +403,11 @@ int mio_is_perenced_http_bcstr (const mio_bch_t* str)
|
|||||||
{
|
{
|
||||||
if (*p == '%' && *(p + 1) != '\0' && *(p + 2) != '\0')
|
if (*p == '%' && *(p + 1) != '\0' && *(p + 2) != '\0')
|
||||||
{
|
{
|
||||||
int q = XDIGIT_TO_NUM(*(p + 1));
|
int q = MIO_XDIGIT_TO_NUM(*(p + 1));
|
||||||
if (q >= 0)
|
if (q >= 0)
|
||||||
{
|
{
|
||||||
/* return true if the first valid percent-encoded sequence is found */
|
/* return true if the first valid percent-encoded sequence is found */
|
||||||
int w = XDIGIT_TO_NUM(*(p + 2));
|
int w = MIO_XDIGIT_TO_NUM(*(p + 2));
|
||||||
if (w >= 0) return 1;
|
if (w >= 0) return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -433,10 +428,10 @@ mio_oow_t mio_perdechttpstr (const mio_bch_t* str, mio_bch_t* buf, mio_oow_t* nd
|
|||||||
{
|
{
|
||||||
if (*p == '%' && *(p + 1) != '\0' && *(p + 2) != '\0')
|
if (*p == '%' && *(p + 1) != '\0' && *(p + 2) != '\0')
|
||||||
{
|
{
|
||||||
int q = XDIGIT_TO_NUM(*(p + 1));
|
int q = MIO_XDIGIT_TO_NUM(*(p + 1));
|
||||||
if (q >= 0)
|
if (q >= 0)
|
||||||
{
|
{
|
||||||
int w = XDIGIT_TO_NUM(*(p + 2));
|
int w = MIO_XDIGIT_TO_NUM(*(p + 2));
|
||||||
if (w >= 0)
|
if (w >= 0)
|
||||||
{
|
{
|
||||||
/* we don't care if it contains a null character */
|
/* we don't care if it contains a null character */
|
||||||
|
@ -84,6 +84,13 @@ typedef enum mio_ooch_prop_t mio_ooch_prop_t;
|
|||||||
typedef enum mio_ooch_prop_t mio_uch_prop_t;
|
typedef enum mio_ooch_prop_t mio_uch_prop_t;
|
||||||
typedef enum mio_ooch_prop_t mio_bch_prop_t;
|
typedef enum mio_ooch_prop_t mio_bch_prop_t;
|
||||||
|
|
||||||
|
#define MIO_DIGIT_TO_NUM(c) (((c) >= '0' && (c) <= '9')? ((c) - '0'): -1)
|
||||||
|
|
||||||
|
#define MIO_XDIGIT_TO_NUM(c) \
|
||||||
|
(((c) >= '0' && (c) <= '9')? ((c) - '0'): \
|
||||||
|
((c) >= 'A' && (c) <= 'F')? ((c) - 'A' + 10): \
|
||||||
|
((c) >= 'a' && (c) <= 'f')? ((c) - 'a' + 10): -1)
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
@ -76,7 +76,7 @@ struct mio_htrd_recbs_t
|
|||||||
|
|
||||||
struct mio_htrd_t
|
struct mio_htrd_t
|
||||||
{
|
{
|
||||||
mio_mmgr_t* mmgr;
|
mio_t* mio;
|
||||||
mio_htrd_errnum_t errnum;
|
mio_htrd_errnum_t errnum;
|
||||||
int option;
|
int option;
|
||||||
int flags;
|
int flags;
|
||||||
@ -90,13 +90,13 @@ struct mio_htrd_t
|
|||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
int crlf; /* crlf status */
|
int crlf; /* crlf status */
|
||||||
mio_size_t plen; /* raw request length excluding crlf */
|
mio_oow_t plen; /* raw request length excluding crlf */
|
||||||
mio_size_t need; /* number of octets needed for contents */
|
mio_oow_t need; /* number of octets needed for contents */
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
mio_size_t len;
|
mio_oow_t len;
|
||||||
mio_size_t count;
|
mio_oow_t count;
|
||||||
int phase;
|
int phase;
|
||||||
} chunk;
|
} chunk;
|
||||||
} s; /* state */
|
} s; /* state */
|
||||||
@ -104,8 +104,8 @@ struct mio_htrd_t
|
|||||||
/* buffers needed for processing a request */
|
/* buffers needed for processing a request */
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
mio_htob_t raw; /* buffer to hold raw octets */
|
mio_becs_t raw; /* buffer to hold raw octets */
|
||||||
mio_htob_t tra; /* buffer for handling trailers */
|
mio_becs_t tra; /* buffer for handling trailers */
|
||||||
} b;
|
} b;
|
||||||
} fed;
|
} fed;
|
||||||
|
|
||||||
@ -121,8 +121,8 @@ extern "C" {
|
|||||||
* The mio_htrd_open() function creates a htrd processor.
|
* The mio_htrd_open() function creates a htrd processor.
|
||||||
*/
|
*/
|
||||||
MIO_EXPORT mio_htrd_t* mio_htrd_open (
|
MIO_EXPORT mio_htrd_t* mio_htrd_open (
|
||||||
mio_mmgr_t* mmgr, /**< memory manager */
|
mio_t* mio, /**< memory manager */
|
||||||
mio_size_t xtnsize /**< extension size in bytes */
|
mio_oow_t xtnsize /**< extension size in bytes */
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -134,20 +134,18 @@ MIO_EXPORT void mio_htrd_close (
|
|||||||
|
|
||||||
MIO_EXPORT int mio_htrd_init (
|
MIO_EXPORT int mio_htrd_init (
|
||||||
mio_htrd_t* htrd,
|
mio_htrd_t* htrd,
|
||||||
mio_mmgr_t* mmgr
|
mio_t* mio
|
||||||
);
|
);
|
||||||
|
|
||||||
MIO_EXPORT void mio_htrd_fini (
|
MIO_EXPORT void mio_htrd_fini (
|
||||||
mio_htrd_t* htrd
|
mio_htrd_t* htrd
|
||||||
);
|
);
|
||||||
|
|
||||||
MIO_EXPORT mio_mmgr_t* mio_htrd_getmmgr (
|
#if defined(MIO_HAVE_INLINE)
|
||||||
mio_htrd_t* htrd
|
static MIO_INLINE void* mio_htrd_getxtn (mio_htrd_t* htrd) { return (void*)(htrd + 1); }
|
||||||
);
|
#else
|
||||||
|
#define mio_htrd_getxtn(htrd) ((void*)((mio_htrd_t*)(htrd) + 1))
|
||||||
MIO_EXPORT void* mio_htrd_getxtn (
|
#endif
|
||||||
mio_htrd_t* htrd
|
|
||||||
);
|
|
||||||
|
|
||||||
MIO_EXPORT mio_htrd_errnum_t mio_htrd_geterrnum (
|
MIO_EXPORT mio_htrd_errnum_t mio_htrd_geterrnum (
|
||||||
mio_htrd_t* htrd
|
mio_htrd_t* htrd
|
||||||
@ -181,8 +179,8 @@ MIO_EXPORT void mio_htrd_setrecbs (
|
|||||||
*/
|
*/
|
||||||
MIO_EXPORT int mio_htrd_feed (
|
MIO_EXPORT int mio_htrd_feed (
|
||||||
mio_htrd_t* htrd, /**< htrd */
|
mio_htrd_t* htrd, /**< htrd */
|
||||||
const mio_mchar_t* req, /**< request octets */
|
const mio_bch_t* req, /**< request octets */
|
||||||
mio_size_t len /**< number of octets */
|
mio_oow_t len /**< number of octets */
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -210,10 +208,12 @@ MIO_EXPORT void mio_htrd_undummify (
|
|||||||
mio_htrd_t* htrd
|
mio_htrd_t* htrd
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
MIO_EXPORT int mio_htrd_scanqparam (
|
MIO_EXPORT int mio_htrd_scanqparam (
|
||||||
mio_htrd_t* http,
|
mio_htrd_t* http,
|
||||||
const mio_mcstr_t* cstr
|
const mio_bcs_t* cstr
|
||||||
);
|
);
|
||||||
|
*/
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
}
|
}
|
||||||
|
@ -130,7 +130,7 @@ struct mio_htre_t
|
|||||||
mio_htb_t trailers;
|
mio_htb_t trailers;
|
||||||
|
|
||||||
/* content octets */
|
/* content octets */
|
||||||
mio_htob_t content;
|
mio_becs_t content;
|
||||||
|
|
||||||
/* content callback */
|
/* content callback */
|
||||||
mio_htre_concb_t concb;
|
mio_htre_concb_t concb;
|
||||||
|
@ -31,12 +31,6 @@
|
|||||||
* This file provides basic data types and functions for the http protocol.
|
* This file provides basic data types and functions for the http protocol.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* octet buffer */
|
|
||||||
typedef mio_becs_t mio_htob_t;
|
|
||||||
|
|
||||||
/* octet string */
|
|
||||||
typedef mio_bcs_t mio_htos_t;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The mio_http_version_t type defines http version.
|
* The mio_http_version_t type defines http version.
|
||||||
*/
|
*/
|
||||||
|
@ -274,6 +274,20 @@ MIO_EXPORT int mio_comp_bcstr (
|
|||||||
int ignorecase
|
int ignorecase
|
||||||
);
|
);
|
||||||
|
|
||||||
|
MIO_EXPORT int mio_comp_ucstr_limited (
|
||||||
|
const mio_uch_t* str1,
|
||||||
|
const mio_uch_t* str2,
|
||||||
|
mio_oow_t maxlen,
|
||||||
|
int ignorecase
|
||||||
|
);
|
||||||
|
|
||||||
|
MIO_EXPORT int mio_comp_bcstr_limited (
|
||||||
|
const mio_bch_t* str1,
|
||||||
|
const mio_bch_t* str2,
|
||||||
|
mio_oow_t maxlen,
|
||||||
|
int ignorecase
|
||||||
|
);
|
||||||
|
|
||||||
MIO_EXPORT int mio_comp_ucstr_bcstr (
|
MIO_EXPORT int mio_comp_ucstr_bcstr (
|
||||||
const mio_uch_t* str1,
|
const mio_uch_t* str1,
|
||||||
const mio_bch_t* str2,
|
const mio_bch_t* str2,
|
||||||
@ -391,6 +405,20 @@ MIO_EXPORT void mio_fill_bchars (
|
|||||||
mio_oow_t len
|
mio_oow_t len
|
||||||
);
|
);
|
||||||
|
|
||||||
|
MIO_EXPORT const mio_bch_t* mio_find_bcstr_word_in_bcstr (
|
||||||
|
const mio_bch_t* str,
|
||||||
|
const mio_bch_t* word,
|
||||||
|
mio_bch_t extra_delim,
|
||||||
|
int ignorecase
|
||||||
|
);
|
||||||
|
|
||||||
|
MIO_EXPORT const mio_uch_t* mio_find_ucstr_word_in_ucstr (
|
||||||
|
const mio_uch_t* str,
|
||||||
|
const mio_uch_t* word,
|
||||||
|
mio_uch_t extra_delim,
|
||||||
|
int ignorecase
|
||||||
|
);
|
||||||
|
|
||||||
MIO_EXPORT mio_uch_t* mio_find_uchar (
|
MIO_EXPORT mio_uch_t* mio_find_uchar (
|
||||||
const mio_uch_t* ptr,
|
const mio_uch_t* ptr,
|
||||||
mio_oow_t len,
|
mio_oow_t len,
|
||||||
@ -469,10 +497,11 @@ MIO_EXPORT mio_oow_t mio_count_bcstr (
|
|||||||
# define mio_copy_oocstr mio_copy_ucstr
|
# define mio_copy_oocstr mio_copy_ucstr
|
||||||
# define mio_copy_oocstr_unlimited mio_copy_ucstr_unlimited
|
# define mio_copy_oocstr_unlimited mio_copy_ucstr_unlimited
|
||||||
|
|
||||||
# define mio_fill_oochars(dst,ch,len) mio_fill_uchars(dst,ch,len)
|
# define mio_fill_oochars mio_fill_uchars
|
||||||
# define mio_find_oochar(ptr,len,c) mio_find_uchar(ptr,len,c)
|
# define mio_find_oocstr_word_in_oocstr mio_find_ucstr_word_in_ucstr
|
||||||
# define mio_rfind_oochar(ptr,len,c) mio_rfind_uchar(ptr,len,c)
|
# define mio_find_oochar mio_find_uchar
|
||||||
# define mio_find_oochar_in_oocstr(ptr,c) mio_find_uchar_in_ucstr(ptr,c)
|
# define mio_rfind_oochar mio_rfind_uchar
|
||||||
|
# define mio_find_oochar_in_oocstr mio_find_uchar_in_ucstr
|
||||||
|
|
||||||
# define mio_split_oocstr mio_split_ucstr
|
# define mio_split_oocstr mio_split_ucstr
|
||||||
# define mio_count_oocstr mio_count_ucstr
|
# define mio_count_oocstr mio_count_ucstr
|
||||||
@ -496,10 +525,11 @@ MIO_EXPORT mio_oow_t mio_count_bcstr (
|
|||||||
# define mio_copy_oocstr mio_copy_bcstr
|
# define mio_copy_oocstr mio_copy_bcstr
|
||||||
# define mio_copy_oocstr_unlimited mio_copy_bcstr_unlimited
|
# define mio_copy_oocstr_unlimited mio_copy_bcstr_unlimited
|
||||||
|
|
||||||
# define mio_fill_oochars(dst,ch,len) mio_fill_bchars(dst,ch,len)
|
# define mio_fill_oochars mio_fill_bchars
|
||||||
# define mio_find_oochar(ptr,len,c) mio_find_bchar(ptr,len,c)
|
# define mio_find_oocstr_word_in_oocstr mio_find_bcstr_word_in_bcstr
|
||||||
# define mio_rfind_oochar(ptr,len,c) mio_rfind_bchar(ptr,len,c)
|
# define mio_find_oochar mio_find_bchar
|
||||||
# define mio_find_oochar_in_oocstr(ptr,c) mio_find_bchar_in_bcstr(ptr,c)
|
# define mio_rfind_oochar mio_rfind_bchar
|
||||||
|
# define mio_find_oochar_in_oocstr mio_find_bchar_in_bcstr
|
||||||
|
|
||||||
# define mio_split_oocstr mio_split_bcstr
|
# define mio_split_oocstr mio_split_bcstr
|
||||||
# define mio_count_oocstr mio_count_bcstr
|
# define mio_count_oocstr mio_count_bcstr
|
||||||
|
@ -1606,7 +1606,7 @@ static int fmt_put_bchars_to_uch_buf (mio_fmtout_t* fmtout, const mio_bch_t* ptr
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (b->mio) mio_seterrnum (b->mio, MIO_EECERR);
|
mio_seterrnum (b->mio, MIO_EECERR);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1717,7 +1717,7 @@ static int fmt_put_uchars_to_bch_buf (mio_fmtout_t* fmtout, const mio_uch_t* ptr
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (b->mio) mio_seterrnum (b->mio, MIO_EECERR);
|
mio_seterrnum (b->mio, MIO_EECERR);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
#include <sys/uio.h>
|
||||||
|
|
||||||
/* ========================================================================= */
|
/* ========================================================================= */
|
||||||
|
|
||||||
|
173
mio/lib/utl.c
173
mio/lib/utl.c
@ -25,7 +25,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "mio-prv.h"
|
#include "mio-prv.h"
|
||||||
#include <mio-chr.h>
|
#include "mio-chr.h"
|
||||||
|
|
||||||
/* ========================================================================= */
|
/* ========================================================================= */
|
||||||
|
|
||||||
@ -187,6 +187,58 @@ int mio_comp_bcstr (const mio_bch_t* str1, const mio_bch_t* str2, int ignorecase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int mio_comp_ucstr_limited (const mio_uch_t* str1, const mio_uch_t* str2, mio_oow_t maxlen, int ignorecase)
|
||||||
|
{
|
||||||
|
if (maxlen == 0) return 0;
|
||||||
|
|
||||||
|
if (ignorecase)
|
||||||
|
{
|
||||||
|
while (mio_to_uch_lower(*str1) == mio_to_uch_lower(*str2))
|
||||||
|
{
|
||||||
|
if (*str1 == '\0' || maxlen == 1) return 0;
|
||||||
|
str1++; str2++; maxlen--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((mio_uchu_t)mio_to_uch_lower(*str1) > (mio_uchu_t)mio_to_uch_lower(*str2))? 1: -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (*str1 == *str2)
|
||||||
|
{
|
||||||
|
if (*str1 == '\0' || maxlen == 1) return 0;
|
||||||
|
str1++; str2++; maxlen--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((mio_uchu_t)*str1 > (mio_uchu_t)*str2)? 1: -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int mio_comp_bcstr_limited (const mio_bch_t* str1, const mio_bch_t* str2, mio_oow_t maxlen, int ignorecase)
|
||||||
|
{
|
||||||
|
if (maxlen == 0) return 0;
|
||||||
|
|
||||||
|
if (ignorecase)
|
||||||
|
{
|
||||||
|
while (mio_to_uch_lower(*str1) == mio_to_uch_lower(*str2))
|
||||||
|
{
|
||||||
|
if (*str1 == '\0' || maxlen == 1) return 0;
|
||||||
|
str1++; str2++; maxlen--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((mio_bchu_t)mio_to_uch_lower(*str1) > (mio_bchu_t)mio_to_uch_lower(*str2))? 1: -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (*str1 == *str2)
|
||||||
|
{
|
||||||
|
if (*str1 == '\0' || maxlen == 1) return 0;
|
||||||
|
str1++; str2++; maxlen--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((mio_bchu_t)*str1 > (mio_bchu_t)*str2)? 1: -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int mio_comp_ucstr_bcstr (const mio_uch_t* str1, const mio_bch_t* str2, int ignorecase)
|
int mio_comp_ucstr_bcstr (const mio_uch_t* str1, const mio_bch_t* str2, int ignorecase)
|
||||||
{
|
{
|
||||||
while (*str1 == *str2)
|
while (*str1 == *str2)
|
||||||
@ -204,6 +256,8 @@ int mio_comp_uchars_ucstr (const mio_uch_t* str1, mio_oow_t len, const mio_uch_t
|
|||||||
* of the first string is equal to the terminating null of
|
* of the first string is equal to the terminating null of
|
||||||
* the second string. the first string is still considered
|
* the second string. the first string is still considered
|
||||||
* bigger */
|
* bigger */
|
||||||
|
if (ignorecase)
|
||||||
|
{
|
||||||
const mio_uch_t* end = str1 + len;
|
const mio_uch_t* end = str1 + len;
|
||||||
while (str1 < end && *str2 != '\0')
|
while (str1 < end && *str2 != '\0')
|
||||||
{
|
{
|
||||||
@ -212,8 +266,25 @@ int mio_comp_uchars_ucstr (const mio_uch_t* str1, mio_oow_t len, const mio_uch_t
|
|||||||
}
|
}
|
||||||
return (str1 < end)? 1: (*str2 == '\0'? 0: -1);
|
return (str1 < end)? 1: (*str2 == '\0'? 0: -1);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const mio_uch_t* end = str1 + len;
|
||||||
|
mio_uch_t c1;
|
||||||
|
mio_uch_t c2;
|
||||||
|
while (str1 < end && *str2 != '\0')
|
||||||
|
{
|
||||||
|
c1 = mio_to_uch_lower(*str1);
|
||||||
|
c2 = mio_to_uch_lower(*str2);
|
||||||
|
if (c1 != c2) return ((mio_uchu_t)c1 > (mio_uchu_t)c2)? 1: -1;
|
||||||
|
str1++; str2++;
|
||||||
|
}
|
||||||
|
return (str1 < end)? 1: (*str2 == '\0'? 0: -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int mio_comp_uchars_bcstr (const mio_uch_t* str1, mio_oow_t len, const mio_bch_t* str2, int ignorecase)
|
int mio_comp_uchars_bcstr (const mio_uch_t* str1, mio_oow_t len, const mio_bch_t* str2, int ignorecase)
|
||||||
|
{
|
||||||
|
if (ignorecase)
|
||||||
{
|
{
|
||||||
const mio_uch_t* end = str1 + len;
|
const mio_uch_t* end = str1 + len;
|
||||||
while (str1 < end && *str2 != '\0')
|
while (str1 < end && *str2 != '\0')
|
||||||
@ -223,8 +294,25 @@ int mio_comp_uchars_bcstr (const mio_uch_t* str1, mio_oow_t len, const mio_bch_t
|
|||||||
}
|
}
|
||||||
return (str1 < end)? 1: (*str2 == '\0'? 0: -1);
|
return (str1 < end)? 1: (*str2 == '\0'? 0: -1);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const mio_uch_t* end = str1 + len;
|
||||||
|
mio_uch_t c1;
|
||||||
|
mio_bch_t c2;
|
||||||
|
while (str1 < end && *str2 != '\0')
|
||||||
|
{
|
||||||
|
c1 = mio_to_uch_lower(*str1);
|
||||||
|
c2 = mio_to_bch_lower(*str2);
|
||||||
|
if (c1 != c2) return ((mio_uchu_t)c1 > (mio_bchu_t)c2)? 1: -1;
|
||||||
|
str1++; str2++;
|
||||||
|
}
|
||||||
|
return (str1 < end)? 1: (*str2 == '\0'? 0: -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int mio_comp_bchars_bcstr (const mio_bch_t* str1, mio_oow_t len, const mio_bch_t* str2, int ignorecase)
|
int mio_comp_bchars_bcstr (const mio_bch_t* str1, mio_oow_t len, const mio_bch_t* str2, int ignorecase)
|
||||||
|
{
|
||||||
|
if (ignorecase)
|
||||||
{
|
{
|
||||||
const mio_bch_t* end = str1 + len;
|
const mio_bch_t* end = str1 + len;
|
||||||
while (str1 < end && *str2 != '\0')
|
while (str1 < end && *str2 != '\0')
|
||||||
@ -234,8 +322,25 @@ int mio_comp_bchars_bcstr (const mio_bch_t* str1, mio_oow_t len, const mio_bch_t
|
|||||||
}
|
}
|
||||||
return (str1 < end)? 1: (*str2 == '\0'? 0: -1);
|
return (str1 < end)? 1: (*str2 == '\0'? 0: -1);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const mio_bch_t* end = str1 + len;
|
||||||
|
mio_bch_t c1;
|
||||||
|
mio_bch_t c2;
|
||||||
|
while (str1 < end && *str2 != '\0')
|
||||||
|
{
|
||||||
|
c1 = mio_to_bch_lower(*str1);
|
||||||
|
c2 = mio_to_bch_lower(*str2);
|
||||||
|
if (c1 != c2) return ((mio_bchu_t)c1 > (mio_bchu_t)c2)? 1: -1;
|
||||||
|
str1++; str2++;
|
||||||
|
}
|
||||||
|
return (str1 < end)? 1: (*str2 == '\0'? 0: -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int mio_comp_bchars_ucstr (const mio_bch_t* str1, mio_oow_t len, const mio_uch_t* str2, int ignorecase)
|
int mio_comp_bchars_ucstr (const mio_bch_t* str1, mio_oow_t len, const mio_uch_t* str2, int ignorecase)
|
||||||
|
{
|
||||||
|
if (ignorecase)
|
||||||
{
|
{
|
||||||
const mio_bch_t* end = str1 + len;
|
const mio_bch_t* end = str1 + len;
|
||||||
while (str1 < end && *str2 != '\0')
|
while (str1 < end && *str2 != '\0')
|
||||||
@ -245,6 +350,21 @@ int mio_comp_bchars_ucstr (const mio_bch_t* str1, mio_oow_t len, const mio_uch_t
|
|||||||
}
|
}
|
||||||
return (str1 < end)? 1: (*str2 == '\0'? 0: -1);
|
return (str1 < end)? 1: (*str2 == '\0'? 0: -1);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const mio_bch_t* end = str1 + len;
|
||||||
|
mio_bch_t c1;
|
||||||
|
mio_uch_t c2;
|
||||||
|
while (str1 < end && *str2 != '\0')
|
||||||
|
{
|
||||||
|
c1 = mio_to_bch_lower(*str1);
|
||||||
|
c2 = mio_to_uch_lower(*str2);
|
||||||
|
if (c1 != c2) return ((mio_bchu_t)c1 > (mio_uchu_t)c2)? 1: -1;
|
||||||
|
str1++; str2++;
|
||||||
|
}
|
||||||
|
return (str1 < end)? 1: (*str2 == '\0'? 0: -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* ========================================================================= */
|
/* ========================================================================= */
|
||||||
|
|
||||||
@ -466,6 +586,57 @@ mio_bch_t* mio_find_bchar_in_bcstr (const mio_bch_t* ptr, mio_bch_t c)
|
|||||||
return MIO_NULL;
|
return MIO_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define IS_BCH_WORD_DELIM(x,delim) (mio_is_bch_space(x) || (x) == delim)
|
||||||
|
#define IS_UCH_WORD_DELIM(x,delim) (mio_is_uch_space(x) || (x) == delim)
|
||||||
|
|
||||||
|
const mio_bch_t* mio_find_bcstr_word_in_bcstr (const mio_bch_t* str, const mio_bch_t* word, mio_bch_t extra_delim, int ignorecase)
|
||||||
|
{
|
||||||
|
/* find a full word in a string */
|
||||||
|
|
||||||
|
const mio_bch_t* ptr = str;
|
||||||
|
|
||||||
|
if (extra_delim == '\0') extra_delim = ' ';
|
||||||
|
do
|
||||||
|
{
|
||||||
|
const mio_bch_t* s;
|
||||||
|
|
||||||
|
while (IS_BCH_WORD_DELIM(*ptr,extra_delim)) ptr++;
|
||||||
|
if (*ptr == '\0') return MIO_NULL;
|
||||||
|
|
||||||
|
s = ptr;
|
||||||
|
while (*ptr != '\0' && !IS_BCH_WORD_DELIM(*ptr,extra_delim)) ptr++;
|
||||||
|
|
||||||
|
if (mio_comp_bchars_bcstr(s, ptr - s, word, ignorecase) == 0) return s;
|
||||||
|
}
|
||||||
|
while (*ptr != '\0');
|
||||||
|
|
||||||
|
return MIO_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const mio_uch_t* mio_find_ucstr_word_in_ucstr (const mio_uch_t* str, const mio_uch_t* word, mio_uch_t extra_delim, int ignorecase)
|
||||||
|
{
|
||||||
|
/* find a full word in a string */
|
||||||
|
|
||||||
|
const mio_uch_t* ptr = str;
|
||||||
|
|
||||||
|
if (extra_delim == '\0') extra_delim = ' ';
|
||||||
|
do
|
||||||
|
{
|
||||||
|
const mio_uch_t* s;
|
||||||
|
|
||||||
|
while (IS_UCH_WORD_DELIM(*ptr,extra_delim)) ptr++;
|
||||||
|
if (*ptr == '\0') return MIO_NULL;
|
||||||
|
|
||||||
|
s = ptr;
|
||||||
|
while (*ptr != '\0' && !IS_UCH_WORD_DELIM(*ptr,extra_delim)) ptr++;
|
||||||
|
|
||||||
|
if (mio_comp_uchars_ucstr(s, ptr - s, word, ignorecase) == 0) return s;
|
||||||
|
}
|
||||||
|
while (*ptr != '\0');
|
||||||
|
|
||||||
|
return MIO_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* ========================================================================= */
|
/* ========================================================================= */
|
||||||
#define IS_UCH_SPACE(x) ((x) ==' ' || (x) == '\t' || (x) == '\n' || (x) == '\r')
|
#define IS_UCH_SPACE(x) ((x) ==' ' || (x) == '\t' || (x) == '\n' || (x) == '\r')
|
||||||
#define IS_BCH_SPACE(x) ((x) ==' ' || (x) == '\t' || (x) == '\n' || (x) == '\r')
|
#define IS_BCH_SPACE(x) ((x) ==' ' || (x) == '\t' || (x) == '\n' || (x) == '\r')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user