added ecs and htb

This commit is contained in:
hyung-hwan 2020-04-30 16:20:31 +00:00
parent 26b720099c
commit f1aa019091
13 changed files with 2783 additions and 138 deletions

View File

@ -23,7 +23,11 @@ include_HEADERS = \
mio-cfg.h \
mio-cmn.h \
mio-dns.h \
mio-ecs.h \
mio-fmt.h \
mio-htb.h \
mio-htre.h \
mio-http.h \
mio-nwif.h \
mio-pac1.h \
mio-pro.h \
@ -37,9 +41,12 @@ lib_LTLIBRARIES = libmio.la
libmio_la_SOURCES = \
dns.c \
dns-cli.c \
ecs.c \
ecs-imp.h \
err.c \
fmt.c \
fmt-imp.h \
htb.c \
mio-prv.h \
mio.c \
nwif.c \

View File

@ -139,12 +139,12 @@ am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
libmio_la_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
am_libmio_la_OBJECTS = libmio_la-dns.lo libmio_la-dns-cli.lo \
libmio_la-err.lo libmio_la-fmt.lo libmio_la-mio.lo \
libmio_la-nwif.lo libmio_la-pro.lo libmio_la-sck.lo \
libmio_la-skad.lo libmio_la-sys.lo libmio_la-sys-ass.lo \
libmio_la-sys-err.lo libmio_la-sys-log.lo libmio_la-sys-mux.lo \
libmio_la-sys-tim.lo libmio_la-tmr.lo libmio_la-utf8.lo \
libmio_la-utl.lo
libmio_la-ecs.lo libmio_la-err.lo libmio_la-fmt.lo \
libmio_la-htb.lo libmio_la-mio.lo libmio_la-nwif.lo \
libmio_la-pro.lo libmio_la-sck.lo libmio_la-skad.lo \
libmio_la-sys.lo libmio_la-sys-ass.lo libmio_la-sys-err.lo \
libmio_la-sys-log.lo libmio_la-sys-mux.lo libmio_la-sys-tim.lo \
libmio_la-tmr.lo libmio_la-utf8.lo libmio_la-utl.lo
libmio_la_OBJECTS = $(am_libmio_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
@ -169,8 +169,9 @@ DEFAULT_INCLUDES =
depcomp = $(SHELL) $(top_srcdir)/ac/depcomp
am__maybe_remake_depfiles = depfiles
am__depfiles_remade = ./$(DEPDIR)/libmio_la-dns-cli.Plo \
./$(DEPDIR)/libmio_la-dns.Plo ./$(DEPDIR)/libmio_la-err.Plo \
./$(DEPDIR)/libmio_la-fmt.Plo ./$(DEPDIR)/libmio_la-mio.Plo \
./$(DEPDIR)/libmio_la-dns.Plo ./$(DEPDIR)/libmio_la-ecs.Plo \
./$(DEPDIR)/libmio_la-err.Plo ./$(DEPDIR)/libmio_la-fmt.Plo \
./$(DEPDIR)/libmio_la-htb.Plo ./$(DEPDIR)/libmio_la-mio.Plo \
./$(DEPDIR)/libmio_la-nwif.Plo ./$(DEPDIR)/libmio_la-pro.Plo \
./$(DEPDIR)/libmio_la-sck.Plo ./$(DEPDIR)/libmio_la-skad.Plo \
./$(DEPDIR)/libmio_la-sys-ass.Plo \
@ -399,7 +400,11 @@ include_HEADERS = \
mio-cfg.h \
mio-cmn.h \
mio-dns.h \
mio-ecs.h \
mio-fmt.h \
mio-htb.h \
mio-htre.h \
mio-http.h \
mio-nwif.h \
mio-pac1.h \
mio-pro.h \
@ -413,9 +418,12 @@ lib_LTLIBRARIES = libmio.la
libmio_la_SOURCES = \
dns.c \
dns-cli.c \
ecs.c \
ecs-imp.h \
err.c \
fmt.c \
fmt-imp.h \
htb.c \
mio-prv.h \
mio.c \
nwif.c \
@ -532,8 +540,10 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmio_la-dns-cli.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmio_la-dns.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmio_la-ecs.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmio_la-err.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmio_la-fmt.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmio_la-htb.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmio_la-mio.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmio_la-nwif.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmio_la-pro.Plo@am__quote@ # am--include-marker
@ -593,6 +603,13 @@ libmio_la-dns-cli.lo: dns-cli.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libmio_la-dns-cli.lo `test -f 'dns-cli.c' || echo '$(srcdir)/'`dns-cli.c
libmio_la-ecs.lo: ecs.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libmio_la-ecs.lo -MD -MP -MF $(DEPDIR)/libmio_la-ecs.Tpo -c -o libmio_la-ecs.lo `test -f 'ecs.c' || echo '$(srcdir)/'`ecs.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmio_la-ecs.Tpo $(DEPDIR)/libmio_la-ecs.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ecs.c' object='libmio_la-ecs.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libmio_la-ecs.lo `test -f 'ecs.c' || echo '$(srcdir)/'`ecs.c
libmio_la-err.lo: err.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libmio_la-err.lo -MD -MP -MF $(DEPDIR)/libmio_la-err.Tpo -c -o libmio_la-err.lo `test -f 'err.c' || echo '$(srcdir)/'`err.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmio_la-err.Tpo $(DEPDIR)/libmio_la-err.Plo
@ -607,6 +624,13 @@ libmio_la-fmt.lo: fmt.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libmio_la-fmt.lo `test -f 'fmt.c' || echo '$(srcdir)/'`fmt.c
libmio_la-htb.lo: htb.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libmio_la-htb.lo -MD -MP -MF $(DEPDIR)/libmio_la-htb.Tpo -c -o libmio_la-htb.lo `test -f 'htb.c' || echo '$(srcdir)/'`htb.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmio_la-htb.Tpo $(DEPDIR)/libmio_la-htb.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='htb.c' object='libmio_la-htb.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libmio_la-htb.lo `test -f 'htb.c' || echo '$(srcdir)/'`htb.c
libmio_la-mio.lo: mio.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libmio_la-mio.lo -MD -MP -MF $(DEPDIR)/libmio_la-mio.Tpo -c -o libmio_la-mio.lo `test -f 'mio.c' || echo '$(srcdir)/'`mio.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmio_la-mio.Tpo $(DEPDIR)/libmio_la-mio.Plo
@ -862,8 +886,10 @@ clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
distclean: distclean-am
-rm -f ./$(DEPDIR)/libmio_la-dns-cli.Plo
-rm -f ./$(DEPDIR)/libmio_la-dns.Plo
-rm -f ./$(DEPDIR)/libmio_la-ecs.Plo
-rm -f ./$(DEPDIR)/libmio_la-err.Plo
-rm -f ./$(DEPDIR)/libmio_la-fmt.Plo
-rm -f ./$(DEPDIR)/libmio_la-htb.Plo
-rm -f ./$(DEPDIR)/libmio_la-mio.Plo
-rm -f ./$(DEPDIR)/libmio_la-nwif.Plo
-rm -f ./$(DEPDIR)/libmio_la-pro.Plo
@ -926,8 +952,10 @@ installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/libmio_la-dns-cli.Plo
-rm -f ./$(DEPDIR)/libmio_la-dns.Plo
-rm -f ./$(DEPDIR)/libmio_la-ecs.Plo
-rm -f ./$(DEPDIR)/libmio_la-err.Plo
-rm -f ./$(DEPDIR)/libmio_la-fmt.Plo
-rm -f ./$(DEPDIR)/libmio_la-htb.Plo
-rm -f ./$(DEPDIR)/libmio_la-mio.Plo
-rm -f ./$(DEPDIR)/libmio_la-nwif.Plo
-rm -f ./$(DEPDIR)/libmio_la-pro.Plo

453
mio/lib/ecs-imp.h Normal file
View File

@ -0,0 +1,453 @@
/*
* $Id$
*
Copyright (c) 2006-2020 Chung, Hyung-Hwan. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
str_t* FN(open) (mio_t* gem, mio_oow_t xtnsize, mio_oow_t capa)
{
str_t* str;
str = (str_t*)mio_allocmem(gem, MIO_SIZEOF(str_t) + xtnsize);
if (str)
{
if (FN(init)(str, gem, capa) <= -1)
{
mio_freemem (gem, str);
str = MIO_NULL;
}
else
{
MIO_MEMSET (str + 1, 0, xtnsize);
}
}
return str;
}
void FN(close) (str_t* str)
{
FN(fini) (str);
mio_freemem (str->gem, str);
}
int FN(init) (str_t* str, mio_t* gem, mio_oow_t capa)
{
MIO_MEMSET (str, 0, MIO_SIZEOF(str_t));
str->gem = gem;
str->sizer = MIO_NULL;
if (capa == 0) str->val.ptr = MIO_NULL;
else
{
str->val.ptr = (char_t*)mio_allocmem(gem, MIO_SIZEOF(char_t) * (capa + 1));
if (!str->val.ptr) return -1;
str->val.ptr[0] = '\0';
}
str->val.len = 0;
str->capa = capa;
return 0;
}
void FN(fini) (str_t* str)
{
if (str->val.ptr) mio_freemem (str->gem, str->val.ptr);
}
int FN(yield) (str_t* str, cstr_t* buf, mio_oow_t newcapa)
{
char_t* tmp;
if (newcapa == 0) tmp = MIO_NULL;
else
{
tmp = (char_t*)mio_allocmem(str->gem, MIO_SIZEOF(char_t) * (newcapa + 1));
if (!tmp) return -1;
tmp[0] = '\0';
}
if (buf) *buf = str->val;
str->val.ptr = tmp;
str->val.len = 0;
str->capa = newcapa;
return 0;
}
char_t* FN(yieldptr) (str_t* str, mio_oow_t newcapa)
{
cstr_t mx;
if (FN(yield)(str, &mx, newcapa) <= -1) return MIO_NULL;
return mx.ptr;
}
mio_oow_t FN(setcapa) (str_t* str, mio_oow_t capa)
{
char_t* tmp;
if (capa == str->capa) return capa;
tmp = (char_t*)mio_reallocmem(str->gem, str->val.ptr, MIO_SIZEOF(char_t) * (capa+1));
if (!tmp) return (mio_oow_t)-1;
if (capa < str->val.len)
{
str->val.len = capa;
tmp[capa] = '\0';
}
str->capa = capa;
str->val.ptr = tmp;
return str->capa;
}
mio_oow_t FN(setlen) (str_t* str, mio_oow_t len)
{
if (len == str->val.len) return len;
if (len < str->val.len)
{
str->val.len = len;
str->val.ptr[len] = '\0';
return len;
}
if (len > str->capa)
{
if (FN(setcapa)(str, len) == (mio_oow_t)-1) return (mio_oow_t)-1;
}
while (str->val.len < len) str->val.ptr[str->val.len++] = ' ';
str->val.ptr[str->val.len] = '\0';
return str->val.len;
}
void FN(clear) (str_t* str)
{
str->val.len = 0;
if (str->val.ptr)
{
MIO_ASSERT (str->gem, str->capa >= 1);
str->val.ptr[0] = '\0';
}
}
void FN(swap) (str_t* str, str_t* str1)
{
str_t tmp;
tmp.val.ptr = str->val.ptr;
tmp.val.len = str->val.len;
tmp.capa = str->capa;
tmp.gem = str->gem;
str->val.ptr = str1->val.ptr;
str->val.len = str1->val.len;
str->capa = str1->capa;
str->gem = str1->gem;
str1->val.ptr = tmp.val.ptr;
str1->val.len = tmp.val.len;
str1->capa = tmp.capa;
str1->gem = tmp.gem;
}
mio_oow_t FN(cpy) (str_t* str, const char_t* s)
{
/* TODO: improve it */
return FN(ncpy)(str, s, count_chars(s));
}
mio_oow_t FN(ncpy) (str_t* str, const char_t* s, mio_oow_t len)
{
if (len > str->capa || str->capa <= 0)
{
mio_oow_t tmp;
/* if the current capacity is 0 and the string len to copy is 0
* we can't simply pass 'len' as the new capapcity.
* ecs_setcapa() won't do anything the current capacity of 0
* is the same as new capacity required. note that when str->capa
* is 0, str->val.ptr is MIO_NULL. However, this is copying operation.
* Copying a zero-length string may indicate that str->val.ptr must
* not be MIO_NULL. so I simply pass 1 as the new capacity */
tmp = FN(setcapa)(str, ((str->capa <= 0 && len <= 0)? 1: len));
if (tmp == (mio_oow_t)-1) return (mio_oow_t)-1;
}
MIO_MEMCPY (&str->val.ptr[0], s, len * MIO_SIZEOF(*s));
str->val.ptr[len] = '\0';
str->val.len = len;
return len;
}
mio_oow_t FN(cat) (str_t* str, const char_t* s)
{
/* TODO: improve it. no counting */
return FN(ncat)(str, s, count_chars(s));
}
static int FN(resize_for_ncat) (str_t* str, mio_oow_t len)
{
if (len > str->capa - str->val.len)
{
mio_oow_t ncapa, mincapa;
/* let the minimum capacity be as large as
* to fit in the new substring */
mincapa = str->val.len + len;
if (!str->sizer)
{
/* increase the capacity by the length to add */
ncapa = mincapa;
/* if the new capacity is less than the double,
* just double it */
if (ncapa < str->capa * 2) ncapa = str->capa * 2;
}
else
{
/* let the user determine the new capacity.
* pass the minimum capacity required as a hint */
ncapa = str->sizer(str, mincapa);
/* if no change in capacity, return current length */
if (ncapa == str->capa) return 0;
}
/* change the capacity */
do
{
if (FN(setcapa)(str, ncapa) != (mio_oow_t)-1) break;
if (ncapa <= mincapa) return -1;
ncapa--;
}
while (1);
}
else if (str->capa <= 0 && len <= 0)
{
MIO_ASSERT (str->gem, str->val.ptr == MIO_NULL);
MIO_ASSERT (str->gem, str->val.len <= 0);
if (FN(setcapa)(str, 1) == (mio_oow_t)-1) return -1;
}
return 1;
}
mio_oow_t FN(ncat) (str_t* str, const char_t* s, mio_oow_t len)
{
int n;
mio_oow_t i, j;
n = FN(resize_for_ncat)(str, len);
if (n <= -1) return (mio_oow_t)-1;
if (n == 0) return str->val.len;
if (len > str->capa - str->val.len)
{
/* copy as many characters as the number of cells available.
* if the capacity has been decreased, len is adjusted here */
len = str->capa - str->val.len;
}
/*
MIO_MEMCPY (&str->val.ptr[str->val.len], s, len*MIO_SIZEOF(*s));
str->val.len += len;
str->val.ptr[str->val.len] = T('\0');
*/
for (i = 0, j = str->val.len ; i < len; j++, i++) str->val.ptr[j] = s[i];
str->val.ptr[j] = '\0';
str->val.len = j;
return str->val.len;
}
mio_oow_t FN(nrcat) (str_t* str, const char_t* s, mio_oow_t len)
{
int n;
mio_oow_t i, j;
n = FN(resize_for_ncat)(str, len);
if (n <= -1) return (mio_oow_t)-1;
if (n == 0) return str->val.len;
if (len > str->capa - str->val.len) len = str->capa - str->val.len;
for (i = len, j = str->val.len ; i > 0; j++) str->val.ptr[j] = s[--i];
str->val.ptr[j] = '\0';
str->val.len = j;
return str->val.len;
}
mio_oow_t FN(ccat) (str_t* str, char_t c)
{
return FN(ncat)(str, &c, 1);
}
mio_oow_t FN(nccat) (str_t* str, char_t c, mio_oow_t len)
{
while (len > 0)
{
if (FN(ncat)(str, &c, 1) == (mio_oow_t)-1) return (mio_oow_t)-1;
len--;
}
return str->val.len;
}
mio_oow_t FN(del) (str_t* str, mio_oow_t index, mio_oow_t size)
{
if (str->val.ptr && index < str->val.len && size > 0)
{
mio_oow_t nidx = index + size;
if (nidx >= str->val.len)
{
str->val.ptr[index] = '\0';
str->val.len = index;
}
else
{
MIO_MEMMOVE (&str->val.ptr[index], &str->val.ptr[nidx], MIO_SIZEOF(*str->val.ptr) * (str->val.len - nidx + 1));
str->val.len -= size;
}
}
return str->val.len;
}
mio_oow_t FN(amend) (str_t* str, mio_oow_t pos, mio_oow_t len, const char_t* repl)
{
mio_oow_t max_len;
mio_oow_t repl_len = count_chars(repl);
if (pos >= str->val.len) pos = str->val.len;
max_len = str->val.len - pos;
if (len > max_len) len = max_len;
if (len > repl_len)
{
FN(del) (str, pos, len - repl_len);
}
else if (len < repl_len)
{
mio_oow_t old_ecs_len = str->val.len;
if (FN(setlen)(str, str->val.len + repl_len - len) == (mio_oow_t)-1) return (mio_oow_t)-1;
MIO_MEMMOVE (&str->val.ptr[pos + repl_len], &str->val.ptr[pos + len], MIO_SIZEOF(*repl) * (old_ecs_len - (pos + len)));
}
if (repl_len > 0) MIO_MEMMOVE (&str->val.ptr[pos], repl, MIO_SIZEOF(*repl) * repl_len);
return str->val.len;
}
#if 0
static int FN(put_bchars) (mio_fmtout_t* fmtout, const mio_bch_t* ptr, mio_oow_t len)
{
#if defined(BUILD_UECS)
mio_uecs_t* uecs = (mio_uecs_t*)fmtout->ctx;
if (mio_uecs_ncatbchars(uecs, ptr, len, uecs->gem->cmgr, 1) == (mio_oow_t)-1) return -1;
#else
mio_becs_t* becs = (mio_becs_t*)fmtout->ctx;
if (mio_becs_ncat(becs, ptr, len) == (mio_oow_t)-1) return -1;
#endif
return 1; /* success. carry on */
}
static int FN(put_uchars) (mio_fmtout_t* fmtout, const mio_uch_t* ptr, mio_oow_t len)
{
#if defined(BUILD_UECS)
mio_uecs_t* uecs = (mio_uecs_t*)fmtout->ctx;
if (mio_uecs_ncat(uecs, ptr, len) == (mio_oow_t)-1) return -1;
#else
mio_becs_t* becs = (mio_becs_t*)fmtout->ctx;
if (mio_becs_ncatuchars(becs, ptr, len, becs->gem->cmgr) == (mio_oow_t)-1) return -1;
#endif
return 1; /* success. carry on */
}
mio_oow_t FN(vfcat) (str_t* str, const char_t* fmt, va_list ap)
{
mio_fmtout_t fo;
MIO_MEMSET (&fo, 0, MIO_SIZEOF(fo));
fo.mmgr = str->gem->mmgr;
fo.putbchars = FN(put_bchars);
fo.putuchars = FN(put_uchars);
fo.ctx = str;
#if defined(BUILD_UECS)
if (mio_ufmt_outv(&fo, fmt, ap) <= -1) return -1;
#else
if (mio_bfmt_outv(&fo, fmt, ap) <= -1) return -1;
#endif
return str->val.len;
}
mio_oow_t FN(fcat) (str_t* str, const char_t* fmt, ...)
{
mio_oow_t x;
va_list ap;
va_start (ap, fmt);
x = FN(vfcat)(str, fmt, ap);
va_end (ap);
return x;
}
mio_oow_t FN(vfmt) (str_t* str, const char_t* fmt, va_list ap)
{
mio_fmtout_t fo;
MIO_MEMSET (&fo, 0, MIO_SIZEOF(fo));
fo.mmgr = str->gem->mmgr;
fo.putbchars = FN(put_bchars);
fo.putuchars = FN(put_uchars);
fo.ctx = str;
FN(clear) (str);
#if defined(BUILD_UECS)
if (mio_ufmt_outv(&fo, fmt, ap) <= -1) return -1;
#else
if (mio_bfmt_outv(&fo, fmt, ap) <= -1) return -1;
#endif
return str->val.len;
}
mio_oow_t FN(fmt) (str_t* str, const char_t* fmt, ...)
{
mio_oow_t x;
va_list ap;
va_start (ap, fmt);
x = FN(vfmt)(str, fmt, ap);
va_end (ap);
return x;
}
#endif

103
mio/lib/ecs.c Normal file
View File

@ -0,0 +1,103 @@
/*
* $Id$
*
Copyright (c) 2006-2020 Chung, Hyung-Hwan. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "mio-ecs.h"
#include "mio-prv.h"
#define _FN(type,verb) mio_ ## type ## _ ## verb
/* ------------------------------------------------------------------------- */
#undef FN
#undef T
#undef str_t
#undef char_t
#undef cstr_t
#undef count_chars
#define FN(verb) _FN(becs,verb)
#define T(x) MIO_BT(x)
#define str_t mio_becs_t
#define char_t mio_bch_t
#define cstr_t mio_bcs_t
#define count_chars(x) mio_count_bcstr(x)
#define BUILD_BECS
#include "ecs-imp.h"
/* ------------------------------------------------------------------------- */
#undef FN
#undef T
#undef str_t
#undef char_t
#undef cstr_t
#undef count_chars
#define FN(verb) _FN(uecs,verb)
#define T(x) MIO_UT(x)
#define str_t mio_uecs_t
#define char_t mio_uch_t
#define cstr_t mio_ucs_t
#define count_chars(x) mio_count_ucstr(x)
#define BUILD_UECS
#include "ecs-imp.h"
/* ------------------------------------------------------------------------- */
mio_oow_t mio_becs_ncatuchars (mio_becs_t* str, const mio_uch_t* s, mio_oow_t len, mio_cmgr_t* cmgr)
{
mio_oow_t bcslen, ucslen;
ucslen = len;
if (mio_conv_uchars_to_bchars_with_cmgr(s, &ucslen, MIO_NULL, &bcslen, cmgr) <= -1) return (mio_oow_t)-1;
if (mio_becs_resize_for_ncat(str, bcslen) <= 0) return -1;
ucslen = len;
bcslen = str->capa - str->val.len;
mio_conv_uchars_to_bchars_with_cmgr (s, &ucslen, &str->val.ptr[str->val.len], &bcslen, cmgr);
str->val.len += bcslen;
str->val.ptr[str->val.len] = '\0';
return str->val.len;
}
mio_oow_t mio_uecs_ncatbchars (mio_uecs_t* str, const mio_bch_t* s, mio_oow_t len, mio_cmgr_t* cmgr, int all)
{
mio_oow_t bcslen, ucslen;
bcslen = len;
if (mio_conv_bchars_to_uchars_with_cmgr(s, &bcslen, MIO_NULL, &ucslen, cmgr, all) <= -1) return (mio_oow_t)-1;
if (mio_uecs_resize_for_ncat(str, ucslen) <= 0) return -1;
bcslen = len;
ucslen = str->capa - str->val.len;
mio_conv_bchars_to_uchars_with_cmgr (s, &bcslen, &str->val.ptr[str->val.len], &ucslen, cmgr, all);
str->val.len += ucslen;
str->val.ptr[str->val.len] = '\0';
return str->val.len;
}

732
mio/lib/htb.c Normal file
View File

@ -0,0 +1,732 @@
/*
* $Id$
*
Copyright (c) 2006-2020 Chung, Hyung-Hwan. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <mio-htb.h>
#include "mio-prv.h"
#define pair_t mio_htb_pair_t
#define copier_t mio_htb_copier_t
#define freeer_t mio_htb_freeer_t
#define hasher_t mio_htb_hasher_t
#define comper_t mio_htb_comper_t
#define keeper_t mio_htb_keeper_t
#define sizer_t mio_htb_sizer_t
#define walker_t mio_htb_walker_t
#define cbserter_t mio_htb_cbserter_t
#define style_t mio_htb_style_t
#define style_kind_t mio_htb_style_kind_t
#define KPTR(p) MIO_HTB_KPTR(p)
#define KLEN(p) MIO_HTB_KLEN(p)
#define VPTR(p) MIO_HTB_VPTR(p)
#define VLEN(p) MIO_HTB_VLEN(p)
#define NEXT(p) MIO_HTB_NEXT(p)
#define KTOB(htb,len) ((len)*(htb)->scale[MIO_HTB_KEY])
#define VTOB(htb,len) ((len)*(htb)->scale[MIO_HTB_VAL])
MIO_INLINE pair_t* mio_htb_allocpair (mio_htb_t* htb, void* kptr, mio_oow_t klen, void* vptr, mio_oow_t vlen)
{
pair_t* n;
copier_t kcop, vcop;
mio_oow_t as;
kcop = htb->style->copier[MIO_HTB_KEY];
vcop = htb->style->copier[MIO_HTB_VAL];
as = MIO_SIZEOF(pair_t);
if (kcop == MIO_HTB_COPIER_INLINE) as += MIO_ALIGN_POW2(KTOB(htb,klen), MIO_SIZEOF_VOID_P);
if (vcop == MIO_HTB_COPIER_INLINE) as += VTOB(htb,vlen);
n = (pair_t*) mio_allocmem(htb->mio, as);
if (MIO_UNLIKELY(!n)) return MIO_NULL;
NEXT(n) = MIO_NULL;
KLEN(n) = klen;
if (kcop == MIO_HTB_COPIER_SIMPLE)
{
KPTR(n) = kptr;
}
else if (kcop == MIO_HTB_COPIER_INLINE)
{
KPTR(n) = n + 1;
/* if kptr is MIO_NULL, the inline copier does not fill
* the actual key area */
if (kptr) MIO_MEMCPY (KPTR(n), kptr, KTOB(htb,klen));
}
else
{
KPTR(n) = kcop(htb, kptr, klen);
if (KPTR(n) == MIO_NULL)
{
mio_freemem (htb->mio, n);
return MIO_NULL;
}
}
VLEN(n) = vlen;
if (vcop == MIO_HTB_COPIER_SIMPLE)
{
VPTR(n) = vptr;
}
else if (vcop == MIO_HTB_COPIER_INLINE)
{
VPTR(n) = n + 1;
if (kcop == MIO_HTB_COPIER_INLINE)
VPTR(n) = (mio_uint8_t*)VPTR(n) + MIO_ALIGN_POW2(KTOB(htb,klen), MIO_SIZEOF_VOID_P);
/* if vptr is MIO_NULL, the inline copier does not fill
* the actual value area */
if (vptr) MIO_MEMCPY (VPTR(n), vptr, VTOB(htb,vlen));
}
else
{
VPTR(n) = vcop (htb, vptr, vlen);
if (VPTR(n) != MIO_NULL)
{
if (htb->style->freeer[MIO_HTB_KEY] != MIO_NULL)
htb->style->freeer[MIO_HTB_KEY] (htb, KPTR(n), KLEN(n));
mio_freemem (htb->mio, n);
return MIO_NULL;
}
}
return n;
}
MIO_INLINE void mio_htb_freepair (mio_htb_t* htb, pair_t* pair)
{
if (htb->style->freeer[MIO_HTB_KEY] != MIO_NULL)
htb->style->freeer[MIO_HTB_KEY] (htb, KPTR(pair), KLEN(pair));
if (htb->style->freeer[MIO_HTB_VAL] != MIO_NULL)
htb->style->freeer[MIO_HTB_VAL] (htb, VPTR(pair), VLEN(pair));
mio_freemem (htb->mio, pair);
}
static MIO_INLINE pair_t* change_pair_val (mio_htb_t* htb, pair_t* pair, void* vptr, mio_oow_t vlen)
{
if (VPTR(pair) == vptr && VLEN(pair) == vlen)
{
/* if the old value and the new value are the same,
* it just calls the handler for this condition.
* No value replacement occurs. */
if (htb->style->keeper != MIO_NULL)
{
htb->style->keeper (htb, vptr, vlen);
}
}
else
{
copier_t vcop = htb->style->copier[MIO_HTB_VAL];
void* ovptr = VPTR(pair);
mio_oow_t ovlen = VLEN(pair);
/* place the new value according to the copier */
if (vcop == MIO_HTB_COPIER_SIMPLE)
{
VPTR(pair) = vptr;
VLEN(pair) = vlen;
}
else if (vcop == MIO_HTB_COPIER_INLINE)
{
if (ovlen == vlen)
{
if (vptr) MIO_MEMCPY (VPTR(pair), vptr, VTOB(htb,vlen));
}
else
{
/* need to reconstruct the pair */
pair_t* p = mio_htb_allocpair(htb, KPTR(pair), KLEN(pair), vptr, vlen);
if (MIO_UNLIKELY(!p)) return MIO_NULL;
mio_htb_freepair (htb, pair);
return p;
}
}
else
{
void* nvptr = vcop(htb, vptr, vlen);
if (MIO_UNLIKELY(!nvptr)) return MIO_NULL;
VPTR(pair) = nvptr;
VLEN(pair) = vlen;
}
/* free up the old value */
if (htb->style->freeer[MIO_HTB_VAL] != MIO_NULL)
{
htb->style->freeer[MIO_HTB_VAL] (htb, ovptr, ovlen);
}
}
return pair;
}
static style_t style[] =
{
/* == MIO_HTB_STYLE_DEFAULT == */
{
{
MIO_HTB_COPIER_DEFAULT,
MIO_HTB_COPIER_DEFAULT
},
{
MIO_HTB_FREEER_DEFAULT,
MIO_HTB_FREEER_DEFAULT
},
MIO_HTB_COMPER_DEFAULT,
MIO_HTB_KEEPER_DEFAULT,
MIO_HTB_SIZER_DEFAULT,
MIO_HTB_HASHER_DEFAULT
},
/* == MIO_HTB_STYLE_INLINE_COPIERS == */
{
{
MIO_HTB_COPIER_INLINE,
MIO_HTB_COPIER_INLINE
},
{
MIO_HTB_FREEER_DEFAULT,
MIO_HTB_FREEER_DEFAULT
},
MIO_HTB_COMPER_DEFAULT,
MIO_HTB_KEEPER_DEFAULT,
MIO_HTB_SIZER_DEFAULT,
MIO_HTB_HASHER_DEFAULT
},
/* == MIO_HTB_STYLE_INLINE_KEY_COPIER == */
{
{
MIO_HTB_COPIER_INLINE,
MIO_HTB_COPIER_DEFAULT
},
{
MIO_HTB_FREEER_DEFAULT,
MIO_HTB_FREEER_DEFAULT
},
MIO_HTB_COMPER_DEFAULT,
MIO_HTB_KEEPER_DEFAULT,
MIO_HTB_SIZER_DEFAULT,
MIO_HTB_HASHER_DEFAULT
},
/* == MIO_HTB_STYLE_INLINE_VALUE_COPIER == */
{
{
MIO_HTB_COPIER_DEFAULT,
MIO_HTB_COPIER_INLINE
},
{
MIO_HTB_FREEER_DEFAULT,
MIO_HTB_FREEER_DEFAULT
},
MIO_HTB_COMPER_DEFAULT,
MIO_HTB_KEEPER_DEFAULT,
MIO_HTB_SIZER_DEFAULT,
MIO_HTB_HASHER_DEFAULT
}
};
const style_t* mio_get_htb_style (style_kind_t kind)
{
return &style[kind];
}
mio_htb_t* mio_htb_open (mio_t* mio, mio_oow_t xtnsize, mio_oow_t capa, int factor, int kscale, int vscale)
{
mio_htb_t* htb;
htb = (mio_htb_t*)mio_allocmem(mio, MIO_SIZEOF(mio_htb_t) + xtnsize);
if (MIO_UNLIKELY(!htb)) return MIO_NULL;
if (mio_htb_init(htb, mio, capa, factor, kscale, vscale) <= -1)
{
mio_freemem (mio, htb);
return MIO_NULL;
}
MIO_MEMSET (htb + 1, 0, xtnsize);
return htb;
}
void mio_htb_close (mio_htb_t* htb)
{
mio_htb_fini (htb);
mio_freemem (htb->mio, htb);
}
int mio_htb_init (mio_htb_t* htb, mio_t* mio, mio_oow_t capa, int factor, int kscale, int vscale)
{
/* The initial capacity should be greater than 0.
* Otherwise, it is adjusted to 1 in the release mode */
MIO_ASSERT (mio, capa > 0);
/* The load factor should be between 0 and 100 inclusive.
* In the release mode, a value out of the range is adjusted to 100 */
MIO_ASSERT (mio, factor >= 0 && factor <= 100);
MIO_ASSERT (mio, kscale >= 0 && kscale <= MIO_TYPE_MAX(mio_uint8_t));
MIO_ASSERT (mio, vscale >= 0 && vscale <= MIO_TYPE_MAX(mio_uint8_t));
/* some initial adjustment */
if (capa <= 0) capa = 1;
if (factor > 100) factor = 100;
/* do not zero out the extension */
MIO_MEMSET (htb, 0, MIO_SIZEOF(*htb));
htb->mio = mio;
htb->bucket = mio_allocmem(mio, capa * MIO_SIZEOF(pair_t*));
if (MIO_UNLIKELY(!htb->bucket)) return -1;
/*for (i = 0; i < capa; i++) htb->bucket[i] = MIO_NULL;*/
MIO_MEMSET (htb->bucket, 0, capa * MIO_SIZEOF(pair_t*));
htb->factor = factor;
htb->scale[MIO_HTB_KEY] = (kscale < 1)? 1: kscale;
htb->scale[MIO_HTB_VAL] = (vscale < 1)? 1: vscale;
htb->size = 0;
htb->capa = capa;
htb->threshold = htb->capa * htb->factor / 100;
if (htb->capa > 0 && htb->threshold <= 0) htb->threshold = 1;
htb->style = &style[0];
return 0;
}
void mio_htb_fini (mio_htb_t* htb)
{
mio_htb_clear (htb);
mio_freemem (htb->mio, htb->bucket);
}
const style_t* mio_htb_getstyle (const mio_htb_t* htb)
{
return htb->style;
}
void mio_htb_setstyle (mio_htb_t* htb, const style_t* style)
{
MIO_ASSERT (htb->mio, style != MIO_NULL);
htb->style = style;
}
mio_oow_t mio_htb_getsize (const mio_htb_t* htb)
{
return htb->size;
}
mio_oow_t mio_htb_getcapa (const mio_htb_t* htb)
{
return htb->capa;
}
pair_t* mio_htb_search (const mio_htb_t* htb, const void* kptr, mio_oow_t klen)
{
pair_t* pair;
mio_oow_t hc;
hc = htb->style->hasher(htb,kptr,klen) % htb->capa;
pair = htb->bucket[hc];
while (pair != MIO_NULL)
{
if (htb->style->comper(htb, KPTR(pair), KLEN(pair), kptr, klen) == 0)
{
return pair;
}
pair = NEXT(pair);
}
mio_seterrnum (htb->mio, MIO_ENOENT);
return MIO_NULL;
}
static MIO_INLINE int reorganize (mio_htb_t* htb)
{
mio_oow_t i, hc, new_capa;
pair_t** new_buck;
if (htb->style->sizer)
{
new_capa = htb->style->sizer (htb, htb->capa + 1);
/* if no change in capacity, return success
* without reorganization */
if (new_capa == htb->capa) return 0;
/* adjust to 1 if the new capacity is not reasonable */
if (new_capa <= 0) new_capa = 1;
}
else
{
/* the bucket is doubled until it grows up to 65536 slots.
* once it has reached it, it grows by 65536 slots */
new_capa = (htb->capa >= 65536)? (htb->capa + 65536): (htb->capa << 1);
}
new_buck = (pair_t**)mio_allocmem(htb->mio, new_capa * MIO_SIZEOF(pair_t*));
if (MIO_UNLIKELY(!new_buck))
{
/* reorganization is disabled once it fails */
htb->threshold = 0;
return -1;
}
/*for (i = 0; i < new_capa; i++) new_buck[i] = MIO_NULL;*/
MIO_MEMSET (new_buck, 0, new_capa * MIO_SIZEOF(pair_t*));
for (i = 0; i < htb->capa; i++)
{
pair_t* pair = htb->bucket[i];
while (pair != MIO_NULL)
{
pair_t* next = NEXT(pair);
hc = htb->style->hasher(htb, KPTR(pair), KLEN(pair)) % new_capa;
NEXT(pair) = new_buck[hc];
new_buck[hc] = pair;
pair = next;
}
}
mio_freemem (htb->mio, htb->bucket);
htb->bucket = new_buck;
htb->capa = new_capa;
htb->threshold = htb->capa * htb->factor / 100;
return 0;
}
/* insert options */
#define UPSERT 1
#define UPDATE 2
#define ENSERT 3
#define INSERT 4
static MIO_INLINE pair_t* insert (mio_htb_t* htb, void* kptr, mio_oow_t klen, void* vptr, mio_oow_t vlen, int opt)
{
pair_t* pair, * p, * prev, * next;
mio_oow_t hc;
hc = htb->style->hasher(htb,kptr,klen) % htb->capa;
pair = htb->bucket[hc];
prev = MIO_NULL;
while (pair != MIO_NULL)
{
next = NEXT(pair);
if (htb->style->comper (htb, KPTR(pair), KLEN(pair), kptr, klen) == 0)
{
/* found a pair with a matching key */
switch (opt)
{
case UPSERT:
case UPDATE:
p = change_pair_val (htb, pair, vptr, vlen);
if (p == MIO_NULL)
{
/* error in changing the value */
return MIO_NULL;
}
if (p != pair)
{
/* old pair destroyed. new pair reallocated.
* relink to include the new pair but to drop
* the old pair. */
if (prev == MIO_NULL) htb->bucket[hc] = p;
else NEXT(prev) = p;
NEXT(p) = next;
}
return p;
case ENSERT:
/* return existing pair */
return pair;
case INSERT:
/* return failure */
mio_seterrnum (htb->mio, MIO_EEXIST);
return MIO_NULL;
}
}
prev = pair;
pair = next;
}
if (opt == UPDATE)
{
mio_seterrnum (htb->mio, MIO_ENOENT);
return MIO_NULL;
}
if (htb->threshold > 0 && htb->size >= htb->threshold)
{
/* ingore reorganization error as it simply means
* more bucket collision and performance penalty. */
if (reorganize(htb) == 0)
{
hc = htb->style->hasher(htb,kptr,klen) % htb->capa;
}
}
MIO_ASSERT (htb->mio, pair == MIO_NULL);
pair = mio_htb_allocpair (htb, kptr, klen, vptr, vlen);
if (MIO_UNLIKELY(!pair)) return MIO_NULL; /* error */
NEXT(pair) = htb->bucket[hc];
htb->bucket[hc] = pair;
htb->size++;
return pair; /* new key added */
}
pair_t* mio_htb_upsert (mio_htb_t* htb, void* kptr, mio_oow_t klen, void* vptr, mio_oow_t vlen)
{
return insert (htb, kptr, klen, vptr, vlen, UPSERT);
}
pair_t* mio_htb_ensert (mio_htb_t* htb, void* kptr, mio_oow_t klen, void* vptr, mio_oow_t vlen)
{
return insert (htb, kptr, klen, vptr, vlen, ENSERT);
}
pair_t* mio_htb_insert (mio_htb_t* htb, void* kptr, mio_oow_t klen, void* vptr, mio_oow_t vlen)
{
return insert (htb, kptr, klen, vptr, vlen, INSERT);
}
pair_t* mio_htb_update (mio_htb_t* htb, void* kptr, mio_oow_t klen, void* vptr, mio_oow_t vlen)
{
return insert (htb, kptr, klen, vptr, vlen, UPDATE);
}
pair_t* mio_htb_cbsert (mio_htb_t* htb, void* kptr, mio_oow_t klen, cbserter_t cbserter, void* ctx)
{
pair_t* pair, * p, * prev, * next;
mio_oow_t hc;
hc = htb->style->hasher(htb,kptr,klen) % htb->capa;
pair = htb->bucket[hc];
prev = MIO_NULL;
while (pair != MIO_NULL)
{
next = NEXT(pair);
if (htb->style->comper(htb, KPTR(pair), KLEN(pair), kptr, klen) == 0)
{
/* found a pair with a matching key */
p = cbserter(htb, pair, kptr, klen, ctx);
if (p == MIO_NULL)
{
/* error returned by the callback function */
return MIO_NULL;
}
if (p != pair)
{
/* old pair destroyed. new pair reallocated.
* relink to include the new pair but to drop
* the old pair. */
if (prev == MIO_NULL) htb->bucket[hc] = p;
else NEXT(prev) = p;
NEXT(p) = next;
}
return p;
}
prev = pair;
pair = next;
}
if (htb->threshold > 0 && htb->size >= htb->threshold)
{
/* ingore reorganization error as it simply means
* more bucket collision and performance penalty. */
if (reorganize(htb) == 0)
{
hc = htb->style->hasher(htb,kptr,klen) % htb->capa;
}
}
MIO_ASSERT (htb->mio, pair == MIO_NULL);
pair = cbserter(htb, MIO_NULL, kptr, klen, ctx);
if (MIO_UNLIKELY(!pair)) return MIO_NULL; /* error */
NEXT(pair) = htb->bucket[hc];
htb->bucket[hc] = pair;
htb->size++;
return pair; /* new key added */
}
int mio_htb_delete (mio_htb_t* htb, const void* kptr, mio_oow_t klen)
{
pair_t* pair, * prev;
mio_oow_t hc;
hc = htb->style->hasher(htb,kptr,klen) % htb->capa;
pair = htb->bucket[hc];
prev = MIO_NULL;
while (pair != MIO_NULL)
{
if (htb->style->comper(htb, KPTR(pair), KLEN(pair), kptr, klen) == 0)
{
if (prev == MIO_NULL)
htb->bucket[hc] = NEXT(pair);
else NEXT(prev) = NEXT(pair);
mio_htb_freepair (htb, pair);
htb->size--;
return 0;
}
prev = pair;
pair = NEXT(pair);
}
mio_seterrnum (htb->mio, MIO_ENOENT);
return -1;
}
void mio_htb_clear (mio_htb_t* htb)
{
mio_oow_t i;
pair_t* pair, * next;
for (i = 0; i < htb->capa; i++)
{
pair = htb->bucket[i];
while (pair != MIO_NULL)
{
next = NEXT(pair);
mio_htb_freepair (htb, pair);
htb->size--;
pair = next;
}
htb->bucket[i] = MIO_NULL;
}
}
void mio_htb_walk (mio_htb_t* htb, walker_t walker, void* ctx)
{
mio_oow_t i;
pair_t* pair, * next;
for (i = 0; i < htb->capa; i++)
{
pair = htb->bucket[i];
while (pair != MIO_NULL)
{
next = NEXT(pair);
if (walker(htb, pair, ctx) == MIO_HTB_WALK_STOP) return;
pair = next;
}
}
}
void mio_init_htb_itr (mio_htb_itr_t* itr)
{
itr->pair = MIO_NULL;
itr->buckno = 0;
}
pair_t* mio_htb_getfirstpair (mio_htb_t* htb, mio_htb_itr_t* itr)
{
mio_oow_t i;
pair_t* pair;
for (i = 0; i < htb->capa; i++)
{
pair = htb->bucket[i];
if (pair)
{
itr->buckno = i;
itr->pair = pair;
return pair;
}
}
return MIO_NULL;
}
pair_t* mio_htb_getnextpair (mio_htb_t* htb, mio_htb_itr_t* itr)
{
mio_oow_t i;
pair_t* pair;
pair = NEXT(itr->pair);
if (pair)
{
/* no change in bucket number */
itr->pair = pair;
return pair;
}
for (i = itr->buckno + 1; i < htb->capa; i++)
{
pair = htb->bucket[i];
if (pair)
{
itr->buckno = i;
itr->pair = pair;
return pair;
}
}
return MIO_NULL;
}
mio_oow_t mio_htb_dflhash (const mio_htb_t* htb, const void* kptr, mio_oow_t klen)
{
mio_oow_t h;
MIO_HASH_BYTES (h, kptr, klen);
return h ;
}
int mio_htb_dflcomp (const mio_htb_t* htb, const void* kptr1, mio_oow_t klen1, const void* kptr2, mio_oow_t klen2)
{
if (klen1 == klen2) return MIO_MEMCMP (kptr1, kptr2, KTOB(htb,klen1));
/* it just returns 1 to indicate that they are different. */
return 1;
}

View File

@ -88,9 +88,9 @@ static MIO_INLINE int xdigit_to_num (mio_bch_t c)
}
static MIO_INLINE int push_to_buffer (mio_htrd_t* htrd, mio_htob_t* octb, const mio_bch_t* ptr, mio_size_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_size_t)-1)
if (mio_mbs_ncat (octb, ptr, len) == (mio_oow_t)-1)
{
htrd->errnum = MIO_HTRD_ENOMEM;
return -1;
@ -98,7 +98,7 @@ static MIO_INLINE int push_to_buffer (mio_htrd_t* htrd, mio_htob_t* octb, const
return 0;
}
static MIO_INLINE int push_content (mio_htrd_t* htrd, const mio_bch_t* ptr, mio_size_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);
@ -126,7 +126,7 @@ static MIO_INLINE void clear_feed (mio_htrd_t* htrd)
MIO_MEMSET (&htrd->fed.s, 0, MIO_SIZEOF(htrd->fed.s));
}
mio_htrd_t* mio_htrd_open (mio_mmgr_t* mmgr, mio_size_t xtnsize)
mio_htrd_t* mio_htrd_open (mio_mmgr_t* mmgr, mio_oow_t xtnsize)
{
mio_htrd_t* htrd;
@ -558,7 +558,7 @@ static int capture_connection (mio_htrd_t* htrd, mio_htb_pair_t* pair)
static int capture_content_length (mio_htrd_t* htrd, mio_htb_pair_t* pair)
{
mio_size_t len = 0, off = 0, tmp;
mio_oow_t len = 0, off = 0, tmp;
const mio_bch_t* ptr;
mio_htre_hdrval_t* val;
@ -671,7 +671,7 @@ static MIO_INLINE int capture_key_header (mio_htrd_t* htrd, mio_htb_pair_t* pair
static struct
{
const mio_bch_t* ptr;
mio_size_t len;
mio_oow_t len;
int (*handler) (mio_htrd_t*, mio_htb_pair_t*);
} hdrtab[] =
{
@ -683,7 +683,7 @@ static MIO_INLINE int capture_key_header (mio_htrd_t* htrd, mio_htb_pair_t* pair
};
int n;
mio_size_t mid, count, base = 0;
mio_oow_t mid, count, base = 0;
/* perform binary search */
for (count = MIO_COUNTOF(hdrtab); count > 0; count /= 2)
@ -712,12 +712,12 @@ struct hdr_cbserter_ctx_t
{
mio_htrd_t* htrd;
void* vptr;
mio_size_t vlen;
mio_oow_t vlen;
};
static mio_htb_pair_t* hdr_cbserter (
mio_htb_t* htb, mio_htb_pair_t* pair,
void* kptr, mio_size_t klen, void* ctx)
void* kptr, mio_oow_t klen, void* ctx)
{
struct hdr_cbserter_ctx_t* tx = (struct hdr_cbserter_ctx_t*)ctx;
@ -824,7 +824,7 @@ mio_bch_t* parse_header_field (mio_htrd_t* htrd, mio_bch_t* line, mio_htb_t* tab
struct
{
mio_bch_t* ptr;
mio_size_t len;
mio_oow_t len;
} name, value;
#if 0
@ -928,7 +928,7 @@ badhdr:
}
static MIO_INLINE int parse_initial_line_and_headers (
mio_htrd_t* htrd, const mio_bch_t* req, mio_size_t rlen)
mio_htrd_t* htrd, const mio_bch_t* req, mio_oow_t rlen)
{
mio_bch_t* p;
@ -980,7 +980,7 @@ static MIO_INLINE int parse_initial_line_and_headers (
#define GET_CHUNK_CRLF 3
#define GET_CHUNK_TRAILERS 4
static const mio_bch_t* getchunklen (mio_htrd_t* htrd, const mio_bch_t* ptr, mio_size_t len)
static const mio_bch_t* getchunklen (mio_htrd_t* htrd, const mio_bch_t* ptr, mio_oow_t len)
{
const mio_bch_t* end = ptr + len;
@ -1122,12 +1122,12 @@ done:
}
/* feed the percent encoded string */
int mio_htrd_feed (mio_htrd_t* htrd, const mio_bch_t* req, mio_size_t len)
int mio_htrd_feed (mio_htrd_t* htrd, const mio_bch_t* req, mio_oow_t len)
{
const mio_bch_t* end = req + len;
const mio_bch_t* ptr = req;
int header_completed_during_this_feed = 0;
mio_size_t avail;
mio_oow_t avail;
MIO_ASSERT (len > 0);

View File

@ -27,7 +27,7 @@
#include <mio-htre.h>
#include "mio-prv.h"
static void free_hdrval (mio_htb_t* htb, void* vptr, mio_size_t vlen)
static void free_hdrval (mio_htb_t* htb, void* vptr, mio_oow_t vlen)
{
mio_htre_hdrval_t* val;
mio_htre_hdrval_t* tmp;
@ -37,11 +37,11 @@ static void free_hdrval (mio_htb_t* htb, void* vptr, mio_size_t vlen)
{
tmp = val;
val = val->next;
MIO_MMGR_FREE (htb->mmgr, tmp);
mio_freemem (htb->mio, tmp);
}
}
int mio_htre_init (mio_htre_t* re, mio_mmgr_t* mmgr)
int mio_htre_init (mio_htre_t* re, mio_t* mio)
{
static mio_htb_style_t style =
{
@ -60,17 +60,17 @@ int mio_htre_init (mio_htre_t* re, mio_mmgr_t* mmgr)
};
MIO_MEMSET (re, 0, MIO_SIZEOF(*re));
re->mmgr = mmgr;
re->mio = mio;
if (mio_htb_init (&re->hdrtab, mmgr, 60, 70, 1, 1) <= -1) return -1;
if (mio_htb_init (&re->trailers, mmgr, 20, 70, 1, 1) <= -1) return -1;
if (mio_htb_init(&re->hdrtab, mio, 60, 70, 1, 1) <= -1) return -1;
if (mio_htb_init(&re->trailers, mio, 20, 70, 1, 1) <= -1) return -1;
mio_htb_setstyle (&re->hdrtab, &style);
mio_htb_setstyle (&re->trailers, &style);
mio_mbs_init (&re->content, mmgr, 0);
mio_becs_init (&re->content, mio, 0);
#if 0
mio_mbs_init (&re->iniline, mmgr, 0);
mio_becs_init (&re->iniline, mio, 0);
#endif
return 0;
@ -79,14 +79,13 @@ int mio_htre_init (mio_htre_t* re, mio_mmgr_t* mmgr)
void mio_htre_fini (mio_htre_t* re)
{
#if 0
mio_mbs_fini (&re->iniline);
mio_becs_fini (&re->iniline);
#endif
mio_mbs_fini (&re->content);
mio_becs_fini (&re->content);
mio_htb_fini (&re->trailers);
mio_htb_fini (&re->hdrtab);
if (re->orgqpath.buf)
MIO_MMGR_FREE (re->mmgr, re->orgqpath.buf);
if (re->orgqpath.buf) mio_freemem (re->mio, re->orgqpath.buf);
}
void mio_htre_clear (mio_htre_t* re)
@ -113,26 +112,24 @@ void mio_htre_clear (mio_htre_t* re)
mio_htb_clear (&re->hdrtab);
mio_htb_clear (&re->trailers);
mio_mbs_clear (&re->content);
mio_becs_clear (&re->content);
#if 0
mio_mbs_clear (&re->iniline);
mio_becs_clear (&re->iniline);
#endif
}
const mio_htre_hdrval_t* mio_htre_getheaderval (
const mio_htre_t* re, const mio_mchar_t* name)
const mio_htre_hdrval_t* mio_htre_getheaderval (const mio_htre_t* re, const mio_bch_t* name)
{
mio_htb_pair_t* pair;
pair = mio_htb_search (&re->hdrtab, name, mio_mbslen(name));
pair = mio_htb_search(&re->hdrtab, name, mio_count_bcstr(name));
if (pair == MIO_NULL) return MIO_NULL;
return MIO_HTB_VPTR(pair);
}
const mio_htre_hdrval_t* mio_htre_gettrailerval (
const mio_htre_t* re, const mio_mchar_t* name)
const mio_htre_hdrval_t* mio_htre_gettrailerval (const mio_htre_t* re, const mio_bch_t* name)
{
mio_htb_pair_t* pair;
pair = mio_htb_search (&re->trailers, name, mio_mbslen(name));
pair = mio_htb_search(&re->trailers, name, mio_count_bcstr(name));
if (pair == MIO_NULL) return MIO_NULL;
return MIO_HTB_VPTR(pair);
}
@ -145,8 +142,7 @@ struct header_walker_ctx_t
int ret;
};
static mio_htb_walk_t walk_headers (
mio_htb_t* htb, mio_htb_pair_t* pair, void* ctx)
static mio_htb_walk_t walk_headers (mio_htb_t* htb, mio_htb_pair_t* pair, void* ctx)
{
struct header_walker_ctx_t* hwctx = (struct header_walker_ctx_t*)ctx;
if (hwctx->walker (hwctx->re, MIO_HTB_KPTR(pair), MIO_HTB_VPTR(pair), hwctx->ctx) <= -1)
@ -157,8 +153,7 @@ static mio_htb_walk_t walk_headers (
return MIO_HTB_WALK_FORWARD;
}
int mio_htre_walkheaders (
mio_htre_t* re, mio_htre_header_walker_t walker, void* ctx)
int mio_htre_walkheaders (mio_htre_t* re, mio_htre_header_walker_t walker, void* ctx)
{
struct header_walker_ctx_t hwctx;
hwctx.re = re;
@ -169,8 +164,7 @@ int mio_htre_walkheaders (
return hwctx.ret;
}
int mio_htre_walktrailers (
mio_htre_t* re, mio_htre_header_walker_t walker, void* ctx)
int mio_htre_walktrailers (mio_htre_t* re, mio_htre_header_walker_t walker, void* ctx)
{
struct header_walker_ctx_t hwctx;
hwctx.re = re;
@ -181,8 +175,7 @@ int mio_htre_walktrailers (
return hwctx.ret;
}
int mio_htre_addcontent (
mio_htre_t* re, const mio_mchar_t* ptr, mio_size_t len)
int mio_htre_addcontent (mio_htre_t* re, const mio_bch_t* ptr, mio_oow_t len)
{
/* see comments in mio_htre_discardcontent() */
@ -191,12 +184,12 @@ int mio_htre_addcontent (
if (re->concb)
{
/* if the callback is set, the content goes to the callback. */
if (re->concb (re, ptr, len, re->concb_ctx) <= -1) return -1;
if (re->concb(re, ptr, len, re->concb_ctx) <= -1) return -1;
}
else
{
/* if the callback is not set, the contents goes to the internal buffer */
if (mio_mbs_ncat (&re->content, ptr, len) == (mio_size_t)-1) return -1;
if (mio_becs_ncat(&re->content, ptr, len) == (mio_oow_t)-1) return -1;
}
return 1; /* added successfully */
@ -225,8 +218,7 @@ void mio_htre_discardcontent (mio_htre_t* re)
* you can't add contents to this if it's completed or discarded
*/
if (!(re->state & MIO_HTRE_COMPLETED) &&
!(re->state & MIO_HTRE_DISCARDED))
if (!(re->state & MIO_HTRE_COMPLETED) && !(re->state & MIO_HTRE_DISCARDED))
{
re->state |= MIO_HTRE_DISCARDED;
@ -243,7 +235,7 @@ void mio_htre_discardcontent (mio_htre_t* re)
* designed to serve a certain usage pattern not including
* weird combinations.
*/
mio_mbs_clear (&re->content);
mio_becs_clear (&re->content);
if (re->concb)
{
/* indicate end of content */
@ -266,34 +258,34 @@ void mio_htre_setconcb (mio_htre_t* re, mio_htre_concb_t concb, void* ctx)
int mio_htre_perdecqpath (mio_htre_t* re)
{
mio_size_t dec_count;
mio_oow_t dec_count;
/* percent decode the query path*/
if (re->type != MIO_HTRE_Q || (re->flags & MIO_HTRE_QPATH_PERDEC)) return -1;
MIO_ASSERT (re->orgqpath.len <= 0);
MIO_ASSERT (re->orgqpath.ptr == MIO_NULL);
MIO_ASSERT (re->mio, re->orgqpath.len <= 0);
MIO_ASSERT (re->mio, re->orgqpath.ptr == MIO_NULL);
if (mio_isperencedhttpstr(re->u.q.path.ptr))
if (mio_is_perenced_http_bcstr(re->u.q.path.ptr))
{
/* the string is percent-encoded. keep the original request
* in a separately allocated buffer */
if (re->orgqpath.buf && re->u.q.path.len <= re->orgqpath.capa)
{
re->orgqpath.len = mio_mbscpy (re->orgqpath.buf, re->u.q.path.ptr);
re->orgqpath.len = mio_copy_bcstr_unlimited(re->orgqpath.buf, re->u.q.path.ptr);
re->orgqpath.ptr = re->orgqpath.buf;
}
else
{
if (re->orgqpath.buf)
{
MIO_MMGR_FREE (re->mmgr, re->orgqpath.buf);
mio_freemem (re->mio, re->orgqpath.buf);
re->orgqpath.capa = 0;
}
re->orgqpath.buf = mio_mbsxdup (re->u.q.path.ptr, re->u.q.path.len, re->mmgr);
re->orgqpath.buf = mio_mbsxdup(re->u.q.path.ptr, re->u.q.path.len, re->mio);
if (!re->orgqpath.buf) return -1;
re->orgqpath.capa = re->u.q.path.len;
@ -309,10 +301,10 @@ int mio_htre_perdecqpath (mio_htre_t* re)
re->u.q.path.len = mio_perdechttpstr (re->u.q.path.ptr, re->u.q.path.ptr, &dec_count);
if (dec_count > 0)
{
/* this assertion is to ensure that mio_isperencedhttpstr()
/* this assertion is to ensure that mio_is_perenced_http_bstr()
* returned true when dec_count is greater than 0 */
MIO_ASSERT (re->orgqpath.buf != MIO_NULL);
MIO_ASSERT (re->orgqpath.ptr != MIO_NULL);
MIO_ASSERT (re->mio, re->orgqpath.buf != MIO_NULL);
MIO_ASSERT (re->mio, re->orgqpath.ptr != MIO_NULL);
re->flags |= MIO_HTRE_QPATH_PERDEC;
}

View File

@ -33,9 +33,9 @@ int mio_comparehttpversions (
return v1->major - v2->major;
}
const mio_mchar_t* mio_httpstatustombs (int code)
const mio_bch_t* mio_httpstatustombs (int code)
{
const mio_mchar_t* msg;
const mio_bch_t* msg;
switch (code)
{
@ -95,10 +95,10 @@ const mio_mchar_t* mio_httpstatustombs (int code)
return msg;
}
const mio_mchar_t* mio_httpmethodtombs (mio_http_method_t type)
const mio_bch_t* mio_httpmethodtombs (mio_http_method_t type)
{
/* keep this table in the same order as mio_httpd_method_t enumerators */
static mio_mchar_t* names[] =
static mio_bch_t* names[] =
{
"OTHER",
@ -117,7 +117,7 @@ const mio_mchar_t* mio_httpmethodtombs (mio_http_method_t type)
struct mtab_t
{
const mio_mchar_t* name;
const mio_bch_t* name;
mio_http_method_t type;
};
@ -134,7 +134,7 @@ static struct mtab_t mtab[] =
{ "TRACE", MIO_HTTP_TRACE }
};
mio_http_method_t mio_mbstohttpmethod (const mio_mchar_t* name)
mio_http_method_t mio_bcstr_to_http_method (const mio_bch_t* name)
{
/* perform binary search */
@ -151,10 +151,10 @@ mio_http_method_t mio_mbstohttpmethod (const mio_mchar_t* name)
mid = left + (right - left) / 2;
entry = &mtab[mid];
n = mio_mbscmp (name, entry->name);
n = mio_comp_bcstr(name, entry->name);
if (n < 0)
{
/* if left, right, mid were of mio_size_t,
/* if left, right, mid were of mio_oow_t,
* you would need the following line.
if (mid == 0) break;
*/
@ -167,7 +167,7 @@ mio_http_method_t mio_mbstohttpmethod (const mio_mchar_t* name)
return MIO_HTTP_OTHER;
}
mio_http_method_t mio_mcstrtohttpmethod (const mio_mcstr_t* name)
mio_http_method_t mio_bchars_to_http_method (const mio_bch_t* nameptr, mio_oow_t namelen)
{
/* perform binary search */
@ -184,10 +184,10 @@ mio_http_method_t mio_mcstrtohttpmethod (const mio_mcstr_t* name)
mid = left + (right - left) / 2;
entry = &mtab[mid];
n = mio_mbsxcmp (name->ptr, name->len, entry->name);
n = mio_mbsxcmp(nameptr, namelen, entry->name);
if (n < 0)
{
/* if left, right, mid were of mio_size_t,
/* if left, right, mid were of mio_oow_t,
* you would need the following line.
if (mid == 0) break;
*/
@ -200,7 +200,7 @@ mio_http_method_t mio_mcstrtohttpmethod (const mio_mcstr_t* name)
return MIO_HTTP_OTHER;
}
int mio_parsehttprange (const mio_mchar_t* str, mio_http_range_t* range)
int mio_parse_http_range_bcstr (const mio_bch_t* str, mio_http_range_t* range)
{
/* NOTE: this function does not support a range set
* like bytes=1-20,30-50 */
@ -255,8 +255,8 @@ int mio_parsehttprange (const mio_mchar_t* str, mio_http_range_t* range)
typedef struct mname_t mname_t;
struct mname_t
{
const mio_mchar_t* s;
const mio_mchar_t* l;
const mio_bch_t* s;
const mio_bch_t* l;
};
static mname_t wday_name[] =
@ -286,11 +286,11 @@ static mname_t mon_name[] =
{ "Dec", "December" }
};
int mio_parsehttptime (const mio_mchar_t* str, mio_ntime_t* nt)
int mio_parse_http_time_bcstr (const mio_bch_t* str, mio_ntime_t* nt)
{
mio_btime_t bt;
const mio_mchar_t* word;
mio_size_t wlen, i;
const mio_bch_t* word;
mio_oow_t wlen, i;
/* TODO: support more formats */
@ -302,7 +302,7 @@ int mio_parsehttptime (const mio_mchar_t* str, mio_ntime_t* nt)
wlen = str - word;
for (i = 0; i < MIO_COUNTOF(wday_name); i++)
{
if (mio_mbsxcmp (word, wlen, wday_name[i].s) == 0)
if (mio_mbsxcmp(word, wlen, wday_name[i].s) == 0)
{
bt.wday = i;
break;
@ -325,7 +325,7 @@ int mio_parsehttptime (const mio_mchar_t* str, mio_ntime_t* nt)
wlen = str - word;
for (i = 0; i < MIO_COUNTOF(mon_name); i++)
{
if (mio_mbsxcmp (word, wlen, mon_name[i].s) == 0)
if (mio_mbsxcmp(word, wlen, mon_name[i].s) == 0)
{
bt.mon = i;
break;
@ -362,15 +362,15 @@ int mio_parsehttptime (const mio_mchar_t* str, mio_ntime_t* nt)
while (MIO_ISMSPACE(*str)) str++;
for (word = str; MIO_ISMALPHA(*str); str++);
wlen = str - word;
if (mio_mbsxcmp (word, wlen, "GMT" != 0) return -1;
if (mio_mbsxcmp(word, wlen, "GMT") != 0) return -1;
while (MIO_ISMSPACE(*str)) str++;
if (*str != '\0') return -1;
return mio_timegm (&bt, nt);
return mio_timegm(&bt, nt);
}
mio_mchar_t* mio_fmthttptime (const mio_ntime_t* nt, mio_mchar_t* buf, mio_size_t bufsz)
mio_bch_t* mio_fmthttptime (const mio_ntime_t* nt, mio_bch_t* buf, mio_oow_t bufsz)
{
mio_btime_t bt;
@ -389,9 +389,9 @@ mio_mchar_t* mio_fmthttptime (const mio_ntime_t* nt, mio_mchar_t* buf, mio_size_
return buf;
}
int mio_isperencedhttpstr (const mio_mchar_t* str)
int mio_is_perenced_http_bcstr (const mio_bch_t* str)
{
const mio_mchar_t* p = str;
const mio_bch_t* p = str;
while (*p != '\0')
{
@ -412,11 +412,11 @@ int mio_isperencedhttpstr (const mio_mchar_t* str)
return 1;
}
mio_size_t mio_perdechttpstr (const mio_mchar_t* str, mio_mchar_t* buf, mio_size_t* ndecs)
mio_oow_t mio_perdechttpstr (const mio_bch_t* str, mio_bch_t* buf, mio_oow_t* ndecs)
{
const mio_mchar_t* p = str;
mio_mchar_t* out = buf;
mio_size_t dec_count = 0;
const mio_bch_t* p = str;
mio_bch_t* out = buf;
mio_oow_t dec_count = 0;
while (*p != '\0')
{
@ -454,11 +454,11 @@ mio_size_t mio_perdechttpstr (const mio_mchar_t* str, mio_mchar_t* buf, mio_size
#define TO_HEX(v) ("0123456789ABCDEF"[(v) & 15])
mio_size_t mio_perenchttpstr (int opt, const mio_mchar_t* str, mio_mchar_t* buf, mio_size_t* nencs)
mio_oow_t mio_perenchttpstr (int opt, const mio_bch_t* str, mio_bch_t* buf, mio_oow_t* nencs)
{
const mio_mchar_t* p = str;
mio_mchar_t* out = buf;
mio_size_t enc_count = 0;
const mio_bch_t* p = str;
mio_bch_t* out = buf;
mio_oow_t enc_count = 0;
/* this function doesn't accept the size of the buffer. the caller must
* ensure that the buffer is large enough */
@ -498,11 +498,11 @@ mio_size_t mio_perenchttpstr (int opt, const mio_mchar_t* str, mio_mchar_t* buf,
return out - buf;
}
mio_mchar_t* mio_perenchttpstrdup (int opt, const mio_mchar_t* str, mio_mmgr_t* mmgr)
mio_bch_t* mio_perenchttpstrdup (int opt, const mio_bch_t* str, mio_mmgr_t* mmgr)
{
mio_mchar_t* buf;
mio_size_t len = 0;
mio_size_t count = 0;
mio_bch_t* buf;
mio_oow_t len = 0;
mio_oow_t count = 0;
/* count the number of characters that should be encoded */
if (opt & MIO_PERENCHTTPSTR_KEEP_SLASH)
@ -521,7 +521,7 @@ mio_mchar_t* mio_perenchttpstrdup (int opt, const mio_mchar_t* str, mio_mmgr_t*
}
/* if there are no characters to escape, just return the original string */
if (count <= 0) return (mio_mchar_t*)str;
if (count <= 0) return (mio_bch_t*)str;
/* allocate a buffer of an optimal size for escaping, otherwise */
buf = MIO_MMGR_ALLOC (mmgr, (len + (count * 2) + 1) * MIO_SIZEOF(*buf));

View File

@ -430,6 +430,13 @@ typedef struct mio_bcs_t mio_bcs_t;
typedef unsigned int mio_bitmask_t;
typedef struct mio_ptl_t mio_ptl_t;
struct mio_ptl_t
{
void* ptr;
mio_oow_t len;
};
/* =========================================================================
* TIME-RELATED TYPES
* =========================================================================*/

640
mio/lib/mio-ecs.h Normal file
View File

@ -0,0 +1,640 @@
/*
* $Id$
*
Copyright (c) 2006-2020 Chung, Hyung-Hwan. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _MIO_ECS_H_
#define _MIO_ECS_H_
#include <mio.h>
#include <stdarg.h>
/** string pointer and length as a aggregate */
#define MIO_BECS_BCS(s) (&((s)->val))
/** string length */
#define MIO_BECS_LEN(s) ((s)->val.len)
/** string pointer */
#define MIO_BECS_PTR(s) ((s)->val.ptr)
/** pointer to a particular position */
#define MIO_BECS_CPTR(s,idx) (&(s)->val.ptr[idx])
/** string capacity */
#define MIO_BECS_CAPA(s) ((s)->capa)
/** character at the given position */
#define MIO_BECS_CHAR(s,idx) ((s)->val.ptr[idx])
/**< last character. unsafe if length <= 0 */
#define MIO_BECS_LASTCHAR(s) ((s)->val.ptr[(s)->val.len-1])
/** string pointer and length as a aggregate */
#define MIO_UECS_UCS(s) (&((s)->val))
/** string length */
#define MIO_UECS_LEN(s) ((s)->val.len)
/** string pointer */
#define MIO_UECS_PTR(s) ((s)->val.ptr)
/** pointer to a particular position */
#define MIO_UECS_CPTR(s,idx) (&(s)->val.ptr[idx])
/** string capacity */
#define MIO_UECS_CAPA(s) ((s)->capa)
/** character at the given position */
#define MIO_UECS_CHAR(s,idx) ((s)->val.ptr[idx])
/**< last character. unsafe if length <= 0 */
#define MIO_UECS_LASTCHAR(s) ((s)->val.ptr[(s)->val.len-1])
typedef struct mio_becs_t mio_becs_t;
typedef struct mio_uecs_t mio_uecs_t;
typedef mio_oow_t (*mio_becs_sizer_t) (
mio_becs_t* data,
mio_oow_t hint
);
typedef mio_oow_t (*mio_uecs_sizer_t) (
mio_uecs_t* data,
mio_oow_t hint
);
#if defined(MIO_OOCH_IS_UCH)
# define MIO_OOECS_OOCS(s) MIO_UECS_UCS(s)
# define MIO_OOECS_LEN(s) MIO_UECS_LEN(s)
# define MIO_OOECS_PTR(s) MIO_UECS_PTR(s)
# define MIO_OOECS_CPTR(s,idx) MIO_UECS_CPTR(s,idx)
# define MIO_OOECS_CAPA(s) MIO_UECS_CAPA(s)
# define MIO_OOECS_CHAR(s,idx) MIO_UECS_CHAR(s,idx)
# define MIO_OOECS_LASTCHAR(s) MIO_UECS_LASTCHAR(s)
# define mio_ooecs_t mio_uecs_t
# define mio_ooecs_sizer_t mio_uecs_sizer_t
#else
# define MIO_OOECS_OOCS(s) MIO_BECS_BCS(s)
# define MIO_OOECS_LEN(s) MIO_BECS_LEN(s)
# define MIO_OOECS_PTR(s) MIO_BECS_PTR(s)
# define MIO_OOECS_CPTR(s,idx) MIO_BECS_CPTR(s,idx)
# define MIO_OOECS_CAPA(s) MIO_BECS_CAPA(s)
# define MIO_OOECS_CHAR(s,idx) MIO_BECS_CHAR(s,idx)
# define MIO_OOECS_LASTCHAR(s) MIO_BECS_LASTCHAR(s)
# define mio_ooecs_t mio_becs_t
# define mio_ooecs_sizer_t mio_becs_sizer_t
#endif
/**
* The mio_becs_t type defines a dynamically resizable multi-byte string.
*/
struct mio_becs_t
{
mio_t* gem;
mio_becs_sizer_t sizer; /**< buffer resizer function */
mio_bcs_t val; /**< buffer/string pointer and lengh */
mio_oow_t capa; /**< buffer capacity */
};
/**
* The mio_uecs_t type defines a dynamically resizable wide-character string.
*/
struct mio_uecs_t
{
mio_t* gem;
mio_uecs_sizer_t sizer; /**< buffer resizer function */
mio_ucs_t val; /**< buffer/string pointer and lengh */
mio_oow_t capa; /**< buffer capacity */
};
#if defined(__cplusplus)
extern "C" {
#endif
/**
* The mio_becs_open() function creates a dynamically resizable multibyte string.
*/
MIO_EXPORT mio_becs_t* mio_becs_open (
mio_t* gem,
mio_oow_t xtnsize,
mio_oow_t capa
);
MIO_EXPORT void mio_becs_close (
mio_becs_t* becs
);
/**
* The mio_becs_init() function initializes a dynamically resizable string
* If the parameter capa is 0, it doesn't allocate the internal buffer
* in advance and always succeeds.
* \return 0 on success, -1 on failure.
*/
MIO_EXPORT int mio_becs_init (
mio_becs_t* becs,
mio_t* gem,
mio_oow_t capa
);
/**
* The mio_becs_fini() function finalizes a dynamically resizable string.
*/
MIO_EXPORT void mio_becs_fini (
mio_becs_t* becs
);
#if defined(MIO_HAVE_INLINE)
static MIO_INLINE void* mio_becs_getxtn (mio_becs_t* becs) { return (void*)(becs + 1); }
#else
#define mio_becs_getxtn(becs) ((void*)((mio_becs_t*)(becs) + 1))
#endif
/**
* The mio_becs_yield() function assigns the buffer to an variable of the
* #mio_bcs_t type and recreate a new buffer of the \a new_capa capacity.
* The function fails if it fails to allocate a new buffer.
* \return 0 on success, and -1 on failure.
*/
MIO_EXPORT int mio_becs_yield (
mio_becs_t* becs, /**< string */
mio_bcs_t* buf, /**< buffer pointer */
mio_oow_t newcapa /**< new capacity */
);
MIO_EXPORT mio_bch_t* mio_becs_yieldptr (
mio_becs_t* becs, /**< string */
mio_oow_t newcapa /**< new capacity */
);
/**
* The mio_becs_getsizer() function gets the sizer.
* \return sizer function set or MIO_NULL if no sizer is set.
*/
#if defined(MIO_HAVE_INLINE)
static MIO_INLINE mio_becs_sizer_t mio_becs_getsizer (mio_becs_t* becs) { return becs->sizer; }
#else
# define mio_becs_getsizer(becs) ((becs)->sizer)
#endif
/**
* The mio_becs_setsizer() function specify a new sizer for a dynamic string.
* With no sizer specified, the dynamic string doubles the current buffer
* when it needs to increase its size. The sizer function is passed a dynamic
* string and the minimum capacity required to hold data after resizing.
* The string is truncated if the sizer function returns a smaller number
* than the hint passed.
*/
#if defined(MIO_HAVE_INLINE)
static MIO_INLINE void mio_becs_setsizer (mio_becs_t* becs, mio_becs_sizer_t sizer) { becs->sizer = sizer; }
#else
# define mio_becs_setsizer(becs,sizerfn) ((becs)->sizer = (sizerfn))
#endif
/**
* The mio_becs_getcapa() function returns the current capacity.
* You may use MIO_STR_CAPA(str) macro for performance sake.
* \return current capacity in number of characters.
*/
#if defined(MIO_HAVE_INLINE)
static MIO_INLINE mio_oow_t mio_becs_getcapa (mio_becs_t* becs) { return MIO_BECS_CAPA(becs); }
#else
# define mio_becs_getcapa(becs) MIO_BECS_CAPA(becs)
#endif
/**
* The mio_becs_setcapa() function sets the new capacity. If the new capacity
* is smaller than the old, the overflowing characters are removed from
* from the buffer.
* \return (mio_oow_t)-1 on failure, new capacity on success
*/
MIO_EXPORT mio_oow_t mio_becs_setcapa (
mio_becs_t* becs,
mio_oow_t capa
);
/**
* The mio_becs_getlen() function return the string length.
*/
#if defined(MIO_HAVE_INLINE)
static MIO_INLINE mio_oow_t mio_becs_getlen (mio_becs_t* becs) { return MIO_BECS_LEN(becs); }
#else
# define mio_becs_getlen(becs) MIO_BECS_LEN(becs)
#endif
/**
* The mio_becs_setlen() function changes the string length.
* \return (mio_oow_t)-1 on failure, new length on success
*/
MIO_EXPORT mio_oow_t mio_becs_setlen (
mio_becs_t* becs,
mio_oow_t len
);
/**
* The mio_becs_clear() funtion deletes all characters in a string and sets
* the length to 0. It doesn't resize the internal buffer.
*/
MIO_EXPORT void mio_becs_clear (
mio_becs_t* becs
);
/**
* The mio_becs_swap() function exchanges the pointers to a buffer between
* two strings. It updates the length and the capacity accordingly.
*/
MIO_EXPORT void mio_becs_swap (
mio_becs_t* becs1,
mio_becs_t* becs2
);
MIO_EXPORT mio_oow_t mio_becs_cpy (
mio_becs_t* becs,
const mio_bch_t* s
);
MIO_EXPORT mio_oow_t mio_becs_ncpy (
mio_becs_t* becs,
const mio_bch_t* s,
mio_oow_t len
);
MIO_EXPORT mio_oow_t mio_becs_cat (
mio_becs_t* becs,
const mio_bch_t* s
);
MIO_EXPORT mio_oow_t mio_becs_ncat (
mio_becs_t* becs,
const mio_bch_t* s,
mio_oow_t len
);
MIO_EXPORT mio_oow_t mio_becs_nrcat (
mio_becs_t* becs,
const mio_bch_t* s,
mio_oow_t len
);
MIO_EXPORT mio_oow_t mio_becs_ccat (
mio_becs_t* becs,
mio_bch_t c
);
MIO_EXPORT mio_oow_t mio_becs_nccat (
mio_becs_t* becs,
mio_bch_t c,
mio_oow_t len
);
MIO_EXPORT mio_oow_t mio_becs_del (
mio_becs_t* becs,
mio_oow_t index,
mio_oow_t size
);
MIO_EXPORT mio_oow_t mio_becs_amend (
mio_becs_t* becs,
mio_oow_t index,
mio_oow_t size,
const mio_bch_t* repl
);
MIO_EXPORT mio_oow_t mio_becs_vfcat (
mio_becs_t* str,
const mio_bch_t* fmt,
va_list ap
);
MIO_EXPORT mio_oow_t mio_becs_fcat (
mio_becs_t* str,
const mio_bch_t* fmt,
...
);
MIO_EXPORT mio_oow_t mio_becs_vfmt (
mio_becs_t* str,
const mio_bch_t* fmt,
va_list ap
);
MIO_EXPORT mio_oow_t mio_becs_fmt (
mio_becs_t* str,
const mio_bch_t* fmt,
...
);
/* ------------------------------------------------------------------------ */
/**
* The mio_uecs_open() function creates a dynamically resizable multibyte string.
*/
MIO_EXPORT mio_uecs_t* mio_uecs_open (
mio_t* gem,
mio_oow_t xtnsize,
mio_oow_t capa
);
MIO_EXPORT void mio_uecs_close (
mio_uecs_t* uecs
);
/**
* The mio_uecs_init() function initializes a dynamically resizable string
* If the parameter capa is 0, it doesn't allocate the internal buffer
* in advance and always succeeds.
* \return 0 on success, -1 on failure.
*/
MIO_EXPORT int mio_uecs_init (
mio_uecs_t* uecs,
mio_t* gem,
mio_oow_t capa
);
/**
* The mio_uecs_fini() function finalizes a dynamically resizable string.
*/
MIO_EXPORT void mio_uecs_fini (
mio_uecs_t* uecs
);
#if defined(MIO_HAVE_INLINE)
static MIO_INLINE void* mio_uecs_getxtn (mio_uecs_t* uecs) { return (void*)(uecs + 1); }
#else
#define mio_uecs_getxtn(uecs) ((void*)((mio_uecs_t*)(uecs) + 1))
#endif
/**
* The mio_uecs_yield() function assigns the buffer to an variable of the
* #mio_ucs_t type and recreate a new buffer of the \a new_capa capacity.
* The function fails if it fails to allocate a new buffer.
* \return 0 on success, and -1 on failure.
*/
MIO_EXPORT int mio_uecs_yield (
mio_uecs_t* uecs, /**< string */
mio_ucs_t* buf, /**< buffer pointer */
mio_oow_t newcapa /**< new capacity */
);
MIO_EXPORT mio_uch_t* mio_uecs_yieldptr (
mio_uecs_t* uecs, /**< string */
mio_oow_t newcapa /**< new capacity */
);
/**
* The mio_uecs_getsizer() function gets the sizer.
* \return sizer function set or MIO_NULL if no sizer is set.
*/
#if defined(MIO_HAVE_INLINE)
static MIO_INLINE mio_uecs_sizer_t mio_uecs_getsizer (mio_uecs_t* uecs) { return uecs->sizer; }
#else
# define mio_uecs_getsizer(uecs) ((uecs)->sizer)
#endif
/**
* The mio_uecs_setsizer() function specify a new sizer for a dynamic string.
* With no sizer specified, the dynamic string doubles the current buffer
* when it needs to increase its size. The sizer function is passed a dynamic
* string and the minimum capacity required to hold data after resizing.
* The string is truncated if the sizer function returns a smaller number
* than the hint passed.
*/
#if defined(MIO_HAVE_INLINE)
static MIO_INLINE void mio_uecs_setsizer (mio_uecs_t* uecs, mio_uecs_sizer_t sizer) { uecs->sizer = sizer; }
#else
# define mio_uecs_setsizer(uecs,sizerfn) ((uecs)->sizer = (sizerfn))
#endif
/**
* The mio_uecs_getcapa() function returns the current capacity.
* You may use MIO_STR_CAPA(str) macro for performance sake.
* \return current capacity in number of characters.
*/
#if defined(MIO_HAVE_INLINE)
static MIO_INLINE mio_oow_t mio_uecs_getcapa (mio_uecs_t* uecs) { return MIO_UECS_CAPA(uecs); }
#else
# define mio_uecs_getcapa(uecs) MIO_UECS_CAPA(uecs)
#endif
/**
* The mio_uecs_setcapa() function sets the new capacity. If the new capacity
* is smaller than the old, the overflowing characters are removed from
* from the buffer.
* \return (mio_oow_t)-1 on failure, new capacity on success
*/
MIO_EXPORT mio_oow_t mio_uecs_setcapa (
mio_uecs_t* uecs,
mio_oow_t capa
);
/**
* The mio_uecs_getlen() function return the string length.
*/
#if defined(MIO_HAVE_INLINE)
static MIO_INLINE mio_oow_t mio_uecs_getlen (mio_uecs_t* uecs) { return MIO_UECS_LEN(uecs); }
#else
# define mio_uecs_getlen(uecs) MIO_UECS_LEN(uecs)
#endif
/**
* The mio_uecs_setlen() function changes the string length.
* \return (mio_oow_t)-1 on failure, new length on success
*/
MIO_EXPORT mio_oow_t mio_uecs_setlen (
mio_uecs_t* uecs,
mio_oow_t len
);
/**
* The mio_uecs_clear() funtion deletes all characters in a string and sets
* the length to 0. It doesn't resize the internal buffer.
*/
MIO_EXPORT void mio_uecs_clear (
mio_uecs_t* uecs
);
/**
* The mio_uecs_swap() function exchanges the pointers to a buffer between
* two strings. It updates the length and the capacity accordingly.
*/
MIO_EXPORT void mio_uecs_swap (
mio_uecs_t* uecs1,
mio_uecs_t* uecs2
);
MIO_EXPORT mio_oow_t mio_uecs_cpy (
mio_uecs_t* uecs,
const mio_uch_t* s
);
MIO_EXPORT mio_oow_t mio_uecs_ncpy (
mio_uecs_t* uecs,
const mio_uch_t* s,
mio_oow_t len
);
MIO_EXPORT mio_oow_t mio_uecs_cat (
mio_uecs_t* uecs,
const mio_uch_t* s
);
MIO_EXPORT mio_oow_t mio_uecs_ncat (
mio_uecs_t* uecs,
const mio_uch_t* s,
mio_oow_t len
);
MIO_EXPORT mio_oow_t mio_uecs_nrcat (
mio_uecs_t* uecs,
const mio_uch_t* s,
mio_oow_t len
);
MIO_EXPORT mio_oow_t mio_uecs_ccat (
mio_uecs_t* uecs,
mio_uch_t c
);
MIO_EXPORT mio_oow_t mio_uecs_nccat (
mio_uecs_t* uecs,
mio_uch_t c,
mio_oow_t len
);
MIO_EXPORT mio_oow_t mio_uecs_del (
mio_uecs_t* uecs,
mio_oow_t index,
mio_oow_t size
);
MIO_EXPORT mio_oow_t mio_uecs_amend (
mio_uecs_t* uecs,
mio_oow_t index,
mio_oow_t size,
const mio_uch_t* repl
);
#if 0
MIO_EXPORT mio_oow_t mio_uecs_vfcat (
mio_uecs_t* str,
const mio_uch_t* fmt,
va_list ap
);
MIO_EXPORT mio_oow_t mio_uecs_fcat (
mio_uecs_t* str,
const mio_uch_t* fmt,
...
);
MIO_EXPORT mio_oow_t mio_uecs_vfmt (
mio_uecs_t* str,
const mio_uch_t* fmt,
va_list ap
);
MIO_EXPORT mio_oow_t mio_uecs_fmt (
mio_uecs_t* str,
const mio_uch_t* fmt,
...
);
#endif
#if defined(MIO_OOCH_IS_UCH)
# define mio_ooecs_open mio_uecs_open
# define mio_ooecs_close mio_uecs_close
# define mio_ooecs_init mio_uecs_init
# define mio_ooecs_fini mio_uecs_fini
# define mio_ooecs_getxtn mio_uecs_getxtn
# define mio_ooecs_yield mio_uecs_yield
# define mio_ooecs_yieldptr mio_uecs_yieldptr
# define mio_ooecs_getsizer mio_uecs_getsizer
# define mio_ooecs_setsizer mio_uecs_setsizer
# define mio_ooecs_getcapa mio_uecs_getcapa
# define mio_ooecs_setcapa mio_uecs_setcapa
# define mio_ooecs_getlen mio_uecs_getlen
# define mio_ooecs_setlen mio_uecs_setlen
# define mio_ooecs_clear mio_uecs_clear
# define mio_ooecs_swap mio_uecs_swap
# define mio_ooecs_cpy mio_uecs_cpy
# define mio_ooecs_ncpy mio_uecs_ncpy
# define mio_ooecs_cat mio_uecs_cat
# define mio_ooecs_ncat mio_uecs_ncat
# define mio_ooecs_nrcat mio_uecs_nrcat
# define mio_ooecs_ccat mio_uecs_ccat
# define mio_ooecs_nccat mio_uecs_nccat
# define mio_ooecs_del mio_uecs_del
# define mio_ooecs_amend mio_uecs_amend
#if 0
# define mio_ooecs_vfcat mio_uecs_vfcat
# define mio_ooecs_fcat mio_uecs_fcat
# define mio_ooecs_vfmt mio_uecs_vfmt
# define mio_ooecs_fmt mio_uecs_fmt
#endif
#else
# define mio_ooecs_open mio_becs_open
# define mio_ooecs_close mio_becs_close
# define mio_ooecs_init mio_becs_init
# define mio_ooecs_fini mio_becs_fini
# define mio_ooecs_getxtn mio_becs_getxtn
# define mio_ooecs_yield mio_becs_yield
# define mio_ooecs_yieldptr mio_becs_yieldptr
# define mio_ooecs_getsizer mio_becs_getsizer
# define mio_ooecs_setsizer mio_becs_setsizer
# define mio_ooecs_getcapa mio_becs_getcapa
# define mio_ooecs_setcapa mio_becs_setcapa
# define mio_ooecs_getlen mio_becs_getlen
# define mio_ooecs_setlen mio_becs_setlen
# define mio_ooecs_clear mio_becs_clear
# define mio_ooecs_swap mio_becs_swap
# define mio_ooecs_cpy mio_becs_cpy
# define mio_ooecs_ncpy mio_becs_ncpy
# define mio_ooecs_cat mio_becs_cat
# define mio_ooecs_ncat mio_becs_ncat
# define mio_ooecs_nrcat mio_becs_nrcat
# define mio_ooecs_ccat mio_becs_ccat
# define mio_ooecs_nccat mio_becs_nccat
# define mio_ooecs_del mio_becs_del
# define mio_ooecs_amend mio_becs_amend
#if 0
# define mio_ooecs_vfcat mio_becs_vfcat
# define mio_ooecs_fcat mio_becs_fcat
# define mio_ooecs_vfmt mio_becs_vfmt
# define mio_ooecs_fmt mio_becs_fmt
#endif
#endif
MIO_EXPORT mio_oow_t mio_becs_ncatuchars (
mio_becs_t* str,
const mio_uch_t* s,
mio_oow_t len,
mio_cmgr_t* cmgr
);
MIO_EXPORT mio_oow_t mio_uecs_ncatbchars (
mio_uecs_t* str,
const mio_bch_t* s,
mio_oow_t len,
mio_cmgr_t* cmgr,
int all
);
#if defined(__cplusplus)
}
#endif
#endif

682
mio/lib/mio-htb.h Normal file
View File

@ -0,0 +1,682 @@
/*
* $Id$
*
Copyright (c) 2006-2020 Chung, Hyung-Hwan. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _MIO_HTB_H_
#define _MIO_HTB_H_
#include <mio.h>
/**@file
* This file provides a hash table encapsulated in the #mio_htb_t type that
* maintains buckets for key/value pairs with the same key hash chained under
* the same bucket. Its interface is very close to #mio_rbt_t.
*
* This sample code adds a series of keys and values and print them
* in the randome order.
* @code
* #include <mio-htb.h>
*
* static mio_htb_walk_t walk (mio_htb_t* htb, mio_htb_pair_t* pair, void* ctx)
* {
* mio_printf (MIO_T("key = %d, value = %d\n"),
* *(int*)MIO_HTB_KPTR(pair), *(int*)MIO_HTB_VPTR(pair));
* return MIO_HTB_WALK_FORWARD;
* }
*
* int main ()
* {
* mio_htb_t* s1;
* int i;
*
* mio_open_stdsios ();
* s1 = mio_htb_open (MIO_MMGR_GETDFL(), 0, 30, 75, 1, 1); // error handling skipped
* mio_htb_setstyle (s1, mio_get_htb_style(MIO_HTB_STYLE_INLINE_COPIERS));
*
* for (i = 0; i < 20; i++)
* {
* int x = i * 20;
* mio_htb_insert (s1, &i, MIO_SIZEOF(i), &x, MIO_SIZEOF(x)); // eror handling skipped
* }
*
* mio_htb_walk (s1, walk, MIO_NULL);
*
* mio_htb_close (s1);
* mio_close_stdsios ();
* return 0;
* }
* @endcode
*/
typedef struct mio_htb_t mio_htb_t;
typedef struct mio_htb_pair_t mio_htb_pair_t;
/**
* The mio_htb_walk_t type defines values that the callback function can
* return to control mio_htb_walk().
*/
enum mio_htb_walk_t
{
MIO_HTB_WALK_STOP = 0,
MIO_HTB_WALK_FORWARD = 1
};
typedef enum mio_htb_walk_t mio_htb_walk_t;
/**
* The mio_htb_id_t type defines IDs to indicate a key or a value in various
* functions.
*/
enum mio_htb_id_t
{
MIO_HTB_KEY = 0,
MIO_HTB_VAL = 1
};
typedef enum mio_htb_id_t mio_htb_id_t;
/**
* The mio_htb_copier_t type defines a pair contruction callback.
* A special copier #MIO_HTB_COPIER_INLINE is provided. This copier enables
* you to copy the data inline to the internal node. No freeer is invoked
* when the node is freeed.
*/
typedef void* (*mio_htb_copier_t) (
mio_htb_t* htb /* hash table */,
void* dptr /* pointer to a key or a value */,
mio_oow_t dlen /* length of a key or a value */
);
/**
* The mio_htb_freeer_t defines a key/value destruction callback
* The freeer is called when a node containing the element is destroyed.
*/
typedef void (*mio_htb_freeer_t) (
mio_htb_t* htb, /**< hash table */
void* dptr, /**< pointer to a key or a value */
mio_oow_t dlen /**< length of a key or a value */
);
/**
* The mio_htb_comper_t type defines a key comparator that is called when
* the htb needs to compare keys. A hash table is created with a default
* comparator which performs bitwise comparison of two keys.
* The comparator should return 0 if the keys are the same and a non-zero
* integer otherwise.
*/
typedef int (*mio_htb_comper_t) (
const mio_htb_t* htb, /**< hash table */
const void* kptr1, /**< key pointer */
mio_oow_t klen1, /**< key length */
const void* kptr2, /**< key pointer */
mio_oow_t klen2 /**< key length */
);
/**
* The mio_htb_keeper_t type defines a value keeper that is called when
* a value is retained in the context that it should be destroyed because
* it is identical to a new value. Two values are identical if their
* pointers and lengths are equal.
*/
typedef void (*mio_htb_keeper_t) (
mio_htb_t* htb, /**< hash table */
void* vptr, /**< value pointer */
mio_oow_t vlen /**< value length */
);
/**
* The mio_htb_sizer_t type defines a bucket size claculator that is called
* when hash table should resize the bucket. The current bucket size + 1 is
* passed as the hint.
*/
typedef mio_oow_t (*mio_htb_sizer_t) (
mio_htb_t* htb, /**< htb */
mio_oow_t hint /**< sizing hint */
);
/**
* The mio_htb_hasher_t type defines a key hash function
*/
typedef mio_oow_t (*mio_htb_hasher_t) (
const mio_htb_t* htb, /**< hash table */
const void* kptr, /**< key pointer */
mio_oow_t klen /**< key length in bytes */
);
/**
* The mio_htb_walker_t defines a pair visitor.
*/
typedef mio_htb_walk_t (*mio_htb_walker_t) (
mio_htb_t* htb, /**< htb */
mio_htb_pair_t* pair, /**< pointer to a key/value pair */
void* ctx /**< pointer to user-defined data */
);
/**
* The mio_htb_cbserter_t type defines a callback function for mio_htb_cbsert().
* The mio_htb_cbserter() function calls it to allocate a new pair for the
* key pointed to by @a kptr of the length @a klen and the callback context
* @a ctx. The second parameter @a pair is passed the pointer to the existing
* pair for the key or #MIO_NULL in case of no existing key. The callback
* must return a pointer to a new or a reallocated pair. When reallocating the
* existing pair, this callback must destroy the existing pair and return the
* newly reallocated pair. It must return #MIO_NULL for failure.
*/
typedef mio_htb_pair_t* (*mio_htb_cbserter_t) (
mio_htb_t* htb, /**< hash table */
mio_htb_pair_t* pair, /**< pair pointer */
void* kptr, /**< key pointer */
mio_oow_t klen, /**< key length */
void* ctx /**< callback context */
);
/**
* The mio_htb_pair_t type defines hash table pair. A pair is composed of a key
* and a value. It maintains pointers to the beginning of a key and a value
* plus their length. The length is scaled down with the scale factor
* specified in an owning hash table.
*/
struct mio_htb_pair_t
{
mio_ptl_t key;
mio_ptl_t val;
/* management information below */
mio_htb_pair_t* next;
};
typedef struct mio_htb_style_t mio_htb_style_t;
struct mio_htb_style_t
{
mio_htb_copier_t copier[2];
mio_htb_freeer_t freeer[2];
mio_htb_comper_t comper; /**< key comparator */
mio_htb_keeper_t keeper; /**< value keeper */
mio_htb_sizer_t sizer; /**< bucket capacity recalculator */
mio_htb_hasher_t hasher; /**< key hasher */
};
/**
* The mio_htb_style_kind_t type defines the type of predefined
* callback set for pair manipulation.
*/
enum mio_htb_style_kind_t
{
/** store the key and the value pointer */
MIO_HTB_STYLE_DEFAULT,
/** copy both key and value into the pair */
MIO_HTB_STYLE_INLINE_COPIERS,
/** copy the key into the pair but store the value pointer */
MIO_HTB_STYLE_INLINE_KEY_COPIER,
/** copy the value into the pair but store the key pointer */
MIO_HTB_STYLE_INLINE_VALUE_COPIER
};
typedef enum mio_htb_style_kind_t mio_htb_style_kind_t;
/**
* The mio_htb_t type defines a hash table.
*/
struct mio_htb_t
{
mio_t* mio;
const mio_htb_style_t* style;
mio_uint8_t scale[2]; /**< length scale */
mio_uint8_t factor; /**< load factor in percentage */
mio_oow_t size;
mio_oow_t capa;
mio_oow_t threshold;
mio_htb_pair_t** bucket;
};
struct mio_htb_itr_t
{
mio_htb_pair_t* pair;
mio_oow_t buckno;
};
typedef struct mio_htb_itr_t mio_htb_itr_t;
/**
* The MIO_HTB_COPIER_SIMPLE macros defines a copier that remembers the
* pointer and length of data in a pair.
**/
#define MIO_HTB_COPIER_SIMPLE ((mio_htb_copier_t)1)
/**
* The MIO_HTB_COPIER_INLINE macros defines a copier that copies data into
* a pair.
**/
#define MIO_HTB_COPIER_INLINE ((mio_htb_copier_t)2)
#define MIO_HTB_COPIER_DEFAULT (MIO_HTB_COPIER_SIMPLE)
#define MIO_HTB_FREEER_DEFAULT (MIO_NULL)
#define MIO_HTB_COMPER_DEFAULT (mio_htb_dflcomp)
#define MIO_HTB_KEEPER_DEFAULT (MIO_NULL)
#define MIO_HTB_SIZER_DEFAULT (MIO_NULL)
#define MIO_HTB_HASHER_DEFAULT (mio_htb_dflhash)
/**
* The MIO_HTB_SIZE() macro returns the number of pairs in a hash table.
*/
#define MIO_HTB_SIZE(m) (*(const mio_oow_t*)&(m)->size)
/**
* The MIO_HTB_CAPA() macro returns the maximum number of pairs that can be
* stored in a hash table without further reorganization.
*/
#define MIO_HTB_CAPA(m) (*(const mio_oow_t*)&(m)->capa)
#define MIO_HTB_FACTOR(m) (*(const int*)&(m)->factor)
#define MIO_HTB_KSCALE(m) (*(const int*)&(m)->scale[MIO_HTB_KEY])
#define MIO_HTB_VSCALE(m) (*(const int*)&(m)->scale[MIO_HTB_VAL])
#define MIO_HTB_KPTL(p) (&(p)->key)
#define MIO_HTB_VPTL(p) (&(p)->val)
#define MIO_HTB_KPTR(p) ((p)->key.ptr)
#define MIO_HTB_KLEN(p) ((p)->key.len)
#define MIO_HTB_VPTR(p) ((p)->val.ptr)
#define MIO_HTB_VLEN(p) ((p)->val.len)
#define MIO_HTB_NEXT(p) ((p)->next)
#if defined(__cplusplus)
extern "C" {
#endif
/**
* The mio_get_htb_style() functions returns a predefined callback set for
* pair manipulation.
*/
MIO_EXPORT const mio_htb_style_t* mio_get_htb_style (
mio_htb_style_kind_t kind
);
/**
* The mio_htb_open() function creates a hash table with a dynamic array
* bucket and a list of values chained. The initial capacity should be larger
* than 0. The load factor should be between 0 and 100 inclusive and the load
* factor of 0 disables bucket resizing. If you need extra space associated
* with hash table, you may pass a non-zero value for @a xtnsize.
* The MIO_HTB_XTN() macro and the mio_htb_getxtn() function return the
* pointer to the beginning of the extension.
* The @a kscale and @a vscale parameters specify the unit of the key and
* value size.
* @return #mio_htb_t pointer on success, #MIO_NULL on failure.
*/
MIO_EXPORT mio_htb_t* mio_htb_open (
mio_t* mio,
mio_oow_t xtnsize, /**< extension size in bytes */
mio_oow_t capa, /**< initial capacity */
int factor, /**< load factor */
int kscale, /**< key scale - 1 to 255 */
int vscale /**< value scale - 1 to 255 */
);
/**
* The mio_htb_close() function destroys a hash table.
*/
MIO_EXPORT void mio_htb_close (
mio_htb_t* htb /**< hash table */
);
/**
* The mio_htb_init() function initializes a hash table
*/
MIO_EXPORT int mio_htb_init (
mio_htb_t* htb, /**< hash table */
mio_t* mio,
mio_oow_t capa, /**< initial capacity */
int factor, /**< load factor */
int kscale, /**< key scale */
int vscale /**< value scale */
);
/**
* The mio_htb_fini() funtion finalizes a hash table
*/
MIO_EXPORT void mio_htb_fini (
mio_htb_t* htb
);
#if defined(MIO_HAVE_INLINE)
static MIO_INLINE void* mio_htb_getxtn (mio_htb_t* htb) { return (void*)(htb + 1); }
#else
#define mio_htb_getxtn(htb) ((void*)((mio_htb_t*)(htb) + 1))
#endif
/**
* The mio_htb_getstyle() function gets manipulation callback function set.
*/
MIO_EXPORT const mio_htb_style_t* mio_htb_getstyle (
const mio_htb_t* htb /**< hash table */
);
/**
* The mio_htb_setstyle() function sets internal manipulation callback
* functions for data construction, destruction, resizing, hashing, etc.
* The callback structure pointed to by \a style must outlive the hash
* table pointed to by \a htb as the hash table doesn't copy the contents
* of the structure.
*/
MIO_EXPORT void mio_htb_setstyle (
mio_htb_t* htb, /**< hash table */
const mio_htb_style_t* style /**< callback function set */
);
/**
* The mio_htb_getsize() function gets the number of pairs in hash table.
*/
MIO_EXPORT mio_oow_t mio_htb_getsize (
const mio_htb_t* htb
);
/**
* The mio_htb_getcapa() function gets the number of slots allocated
* in a hash bucket.
*/
MIO_EXPORT mio_oow_t mio_htb_getcapa (
const mio_htb_t* htb /**< hash table */
);
/**
* The mio_htb_search() function searches a hash table to find a pair with a
* matching key. It returns the pointer to the pair found. If it fails
* to find one, it returns MIO_NULL.
* @return pointer to the pair with a maching key,
* or #MIO_NULL if no match is found.
*/
MIO_EXPORT mio_htb_pair_t* mio_htb_search (
const mio_htb_t* htb, /**< hash table */
const void* kptr, /**< key pointer */
mio_oow_t klen /**< key length */
);
/**
* The mio_htb_upsert() function searches a hash table for the pair with a
* matching key. If one is found, it updates the pair. Otherwise, it inserts
* a new pair with the key and value given. It returns the pointer to the
* pair updated or inserted.
* @return pointer to the updated or inserted pair on success,
* #MIO_NULL on failure.
*/
MIO_EXPORT mio_htb_pair_t* mio_htb_upsert (
mio_htb_t* htb, /**< hash table */
void* kptr, /**< key pointer */
mio_oow_t klen, /**< key length */
void* vptr, /**< value pointer */
mio_oow_t vlen /**< value length */
);
/**
* The mio_htb_ensert() function inserts a new pair with the key and the value
* given. If there exists a pair with the key given, the function returns
* the pair containing the key.
* @return pointer to a pair on success, #MIO_NULL on failure.
*/
MIO_EXPORT mio_htb_pair_t* mio_htb_ensert (
mio_htb_t* htb, /**< hash table */
void* kptr, /**< key pointer */
mio_oow_t klen, /**< key length */
void* vptr, /**< value pointer */
mio_oow_t vlen /**< value length */
);
/**
* The mio_htb_insert() function inserts a new pair with the key and the value
* given. If there exists a pair with the key given, the function returns
* #MIO_NULL without channging the value.
* @return pointer to the pair created on success, #MIO_NULL on failure.
*/
MIO_EXPORT mio_htb_pair_t* mio_htb_insert (
mio_htb_t* htb, /**< hash table */
void* kptr, /**< key pointer */
mio_oow_t klen, /**< key length */
void* vptr, /**< value pointer */
mio_oow_t vlen /**< value length */
);
/**
* The mio_htb_update() function updates the value of an existing pair
* with a matching key.
* @return pointer to the pair on success, #MIO_NULL on no matching pair
*/
MIO_EXPORT mio_htb_pair_t* mio_htb_update (
mio_htb_t* htb, /**< hash table */
void* kptr, /**< key pointer */
mio_oow_t klen, /**< key length */
void* vptr, /**< value pointer */
mio_oow_t vlen /**< value length */
);
/**
* The mio_htb_cbsert() function inserts a key/value pair by delegating pair
* allocation to a callback function. Depending on the callback function,
* it may behave like mio_htb_insert(), mio_htb_upsert(), mio_htb_update(),
* mio_htb_ensert(), or totally differently. The sample code below inserts
* a new pair if the key is not found and appends the new value to the
* existing value delimited by a comma if the key is found.
*
* @code
* #include <mio-htb.h>
*
* mio_htb_walk_t print_map_pair (mio_htb_t* map, mio_htb_pair_t* pair, void* ctx)
* {
* mio_printf (MIO_T("%.*s[%d] => %.*s[%d]\n"),
* MIO_HTB_KLEN(pair), MIO_HTB_KPTR(pair), (int)MIO_HTB_KLEN(pair),
* MIO_HTB_VLEN(pair), MIO_HTB_VPTR(pair), (int)MIO_HTB_VLEN(pair));
* return MIO_HTB_WALK_FORWARD;
* }
*
* mio_htb_pair_t* cbserter (
* mio_htb_t* htb, mio_htb_pair_t* pair,
* void* kptr, mio_oow_t klen, void* ctx)
* {
* mio_cstr_t* v = (mio_cstr_t*)ctx;
* if (pair == MIO_NULL)
* {
* // no existing key for the key
* return mio_htb_allocpair (htb, kptr, klen, v->ptr, v->len);
* }
* else
* {
* // a pair with the key exists.
* // in this sample, i will append the new value to the old value
* // separated by a comma
* mio_htb_pair_t* new_pair;
* mio_ooch_t comma = MIO_T(',');
* mio_uint8_t* vptr;
*
* // allocate a new pair, but without filling the actual value.
* // note vptr is given MIO_NULL for that purpose
* new_pair = mio_htb_allocpair (
* htb, kptr, klen, MIO_NULL, MIO_HTB_VLEN(pair) + 1 + v->len);
* if (new_pair == MIO_NULL) return MIO_NULL;
*
* // fill in the value space
* vptr = MIO_HTB_VPTR(new_pair);
* mio_memcpy (vptr, MIO_HTB_VPTR(pair), MIO_HTB_VLEN(pair)*MIO_SIZEOF(mio_ooch_t));
* vptr += MIO_HTB_VLEN(pair)*MIO_SIZEOF(mio_ooch_t);
* mio_memcpy (vptr, &comma, MIO_SIZEOF(mio_ooch_t));
* vptr += MIO_SIZEOF(mio_ooch_t);
* mio_memcpy (vptr, v->ptr, v->len*MIO_SIZEOF(mio_ooch_t));
*
* // this callback requires the old pair to be destroyed
* mio_htb_freepair (htb, pair);
*
* // return the new pair
* return new_pair;
* }
* }
*
* int main ()
* {
* mio_htb_t* s1;
* int i;
* mio_ooch_t* keys[] = { MIO_T("one"), MIO_T("two"), MIO_T("three") };
* mio_ooch_t* vals[] = { MIO_T("1"), MIO_T("2"), MIO_T("3"), MIO_T("4"), MIO_T("5") };
*
* mio_open_stdsios ();
* s1 = mio_htb_open (
* MIO_MMGR_GETDFL(), 0, 10, 70,
* MIO_SIZEOF(mio_ooch_t), MIO_SIZEOF(mio_ooch_t)
* ); // note error check is skipped
* mio_htb_setstyle (s1, mio_get_htb_style(MIO_HTB_STYLE_INLINE_COPIERS));
*
* for (i = 0; i < MIO_COUNTOF(vals); i++)
* {
* mio_cstr_t ctx;
* ctx.ptr = vals[i]; ctx.len = mio_count_oocstr(vals[i]);
* mio_htb_cbsert (s1,
* keys[i%MIO_COUNTOF(keys)], mio_count_oocstr(keys[i%MIO_COUNTOF(keys)]),
* cbserter, &ctx
* ); // note error check is skipped
* }
* mio_htb_walk (s1, print_map_pair, MIO_NULL);
*
* mio_htb_close (s1);
* mio_close_stdsios ();
* return 0;
* }
* @endcode
*/
MIO_EXPORT mio_htb_pair_t* mio_htb_cbsert (
mio_htb_t* htb, /**< hash table */
void* kptr, /**< key pointer */
mio_oow_t klen, /**< key length */
mio_htb_cbserter_t cbserter, /**< callback function */
void* ctx /**< callback context */
);
/**
* The mio_htb_delete() function deletes a pair with a matching key
* @return 0 on success, -1 on failure
*/
MIO_EXPORT int mio_htb_delete (
mio_htb_t* htb, /**< hash table */
const void* kptr, /**< key pointer */
mio_oow_t klen /**< key length */
);
/**
* The mio_htb_clear() function empties a hash table
*/
MIO_EXPORT void mio_htb_clear (
mio_htb_t* htb /**< hash table */
);
/**
* The mio_htb_walk() function traverses a hash table.
*/
MIO_EXPORT void mio_htb_walk (
mio_htb_t* htb, /**< hash table */
mio_htb_walker_t walker, /**< callback function for each pair */
void* ctx /**< pointer to user-specific data */
);
MIO_EXPORT void mio_init_htb_itr (
mio_htb_itr_t* itr
);
/**
* The mio_htb_getfirstpair() function returns the pointer to the first pair
* in a hash table.
*/
MIO_EXPORT mio_htb_pair_t* mio_htb_getfirstpair (
mio_htb_t* htb, /**< hash table */
mio_htb_itr_t* itr /**< iterator*/
);
/**
* The mio_htb_getnextpair() function returns the pointer to the next pair
* to the current pair @a pair in a hash table.
*/
MIO_EXPORT mio_htb_pair_t* mio_htb_getnextpair (
mio_htb_t* htb, /**< hash table */
mio_htb_itr_t* itr /**< iterator*/
);
/**
* The mio_htb_allocpair() function allocates a pair for a key and a value
* given. But it does not chain the pair allocated into the hash table @a htb.
* Use this function at your own risk.
*
* Take note of he following special behavior when the copier is
* #MIO_HTB_COPIER_INLINE.
* - If @a kptr is #MIO_NULL, the key space of the size @a klen is reserved but
* not propagated with any data.
* - If @a vptr is #MIO_NULL, the value space of the size @a vlen is reserved
* but not propagated with any data.
*/
MIO_EXPORT mio_htb_pair_t* mio_htb_allocpair (
mio_htb_t* htb,
void* kptr,
mio_oow_t klen,
void* vptr,
mio_oow_t vlen
);
/**
* The mio_htb_freepair() function destroys a pair. But it does not detach
* the pair destroyed from the hash table @a htb. Use this function at your
* own risk.
*/
MIO_EXPORT void mio_htb_freepair (
mio_htb_t* htb,
mio_htb_pair_t* pair
);
/**
* The mio_htb_dflhash() function is a default hash function.
*/
MIO_EXPORT mio_oow_t mio_htb_dflhash (
const mio_htb_t* htb,
const void* kptr,
mio_oow_t klen
);
/**
* The mio_htb_dflcomp() function is default comparator.
*/
MIO_EXPORT int mio_htb_dflcomp (
const mio_htb_t* htb,
const void* kptr1,
mio_oow_t klen1,
const void* kptr2,
mio_oow_t klen2
);
#if defined(__cplusplus)
}
#endif
#endif

View File

@ -49,21 +49,21 @@ typedef enum mio_htre_state_t mio_htre_state_t;
typedef int (*mio_htre_concb_t) (
mio_htre_t* re,
const mio_mchar_t* ptr,
mio_size_t len,
const mio_bch_t* ptr,
mio_oow_t len,
void* ctx
);
struct mio_htre_hdrval_t
{
const mio_mchar_t* ptr;
mio_size_t len;
const mio_bch_t* ptr;
mio_oow_t len;
mio_htre_hdrval_t* next;
};
struct mio_htre_t
{
mio_mmgr_t* mmgr;
mio_t* mio;
enum
{
@ -73,7 +73,7 @@ struct mio_htre_t
/* version */
mio_http_version_t version;
const mio_mchar_t* verstr; /* version string include HTTP/ */
const mio_bch_t* verstr; /* version string include HTTP/ */
union
{
@ -82,19 +82,19 @@ struct mio_htre_t
struct
{
mio_http_method_t type;
const mio_mchar_t* name;
const mio_bch_t* name;
} method;
mio_mcstr_t path;
mio_mcstr_t param;
mio_bcs_t path;
mio_bcs_t param;
} q;
struct
{
struct
{
int val;
mio_mchar_t* str;
mio_bch_t* str;
} code;
mio_mchar_t* mesg;
mio_bch_t* mesg;
} s;
} u;
@ -111,18 +111,18 @@ struct mio_htre_t
* meaningful if MIO_HTRE_QPATH_PERDEC is set in the flags */
struct
{
mio_mchar_t* buf; /* buffer pointer */
mio_size_t capa; /* buffer capacity */
mio_bch_t* buf; /* buffer pointer */
mio_oow_t capa; /* buffer capacity */
mio_mchar_t* ptr;
mio_size_t len;
mio_bch_t* ptr;
mio_oow_t len;
} orgqpath;
/* special attributes derived from the header */
struct
{
mio_size_t content_length;
const mio_mchar_t* status; /* for cgi */
mio_oow_t content_length;
const mio_bch_t* status; /* for cgi */
} attr;
/* header table */
@ -130,7 +130,7 @@ struct mio_htre_t
mio_htb_t trailers;
/* content octets */
mio_mbs_t content;
mio_htob_t content;
/* content callback */
mio_htre_concb_t concb;
@ -164,7 +164,7 @@ struct mio_htre_t
typedef int (*mio_htre_header_walker_t) (
mio_htre_t* re,
const mio_mchar_t* key,
const mio_bch_t* key,
const mio_htre_hdrval_t* val,
void* ctx
);
@ -175,7 +175,7 @@ extern "C" {
MIO_EXPORT int mio_htre_init (
mio_htre_t* re,
mio_mmgr_t* mmgr
mio_t* mio
);
MIO_EXPORT void mio_htre_fini (
@ -188,12 +188,12 @@ MIO_EXPORT void mio_htre_clear (
MIO_EXPORT const mio_htre_hdrval_t* mio_htre_getheaderval (
const mio_htre_t* re,
const mio_mchar_t* key
const mio_bch_t* key
);
MIO_EXPORT const mio_htre_hdrval_t* mio_htre_gettrailerval (
const mio_htre_t* re,
const mio_mchar_t* key
const mio_bch_t* key
);
MIO_EXPORT int mio_htre_walkheaders (
@ -217,8 +217,8 @@ MIO_EXPORT int mio_htre_walktrailers (
*/
MIO_EXPORT int mio_htre_addcontent (
mio_htre_t* re,
const mio_mchar_t* ptr,
mio_size_t len
const mio_bch_t* ptr,
mio_oow_t len
);
MIO_EXPORT void mio_htre_completecontent (

View File

@ -25,17 +25,17 @@
#ifndef _MIO_HTTP_H_
#define _MIO_HTTP_H_
#include <mio-cmn.h>
#include <mio-ecs.h>
/** \file
* This file provides basic data types and functions for the http protocol.
*/
/* octet buffer */
typedef mio_mbs_t mio_htob_t;
typedef mio_becs_t mio_htob_t;
/* octet string */
typedef mio_mcstr_t mio_htos_t;
typedef mio_bcs_t mio_htos_t;
/**
* The mio_http_version_t type defines http version.
@ -176,22 +176,23 @@ MIO_EXPORT const mio_bch_t* mio_httpmethodtombs (
mio_http_method_t type
);
MIO_EXPORT mio_http_method_t mio_mbstohttpmethod (
MIO_EXPORT mio_http_method_t mio_bcstr_to_http_method (
const mio_bch_t* name
);
MIO_EXPORT mio_http_method_t mio_mcstrtohttpmethod (
const mio_mcstr_t* name
MIO_EXPORT mio_http_method_t mio_bchars_to_http_method (
const mio_bch_t* nameptr,
mio_oow_t namelen
);
MIO_EXPORT int mio_parsehttprange (
const mio_bch_t* str,
MIO_EXPORT int mio_parse_http_range_bcstr (
const mio_bch_t* str,
mio_http_range_t* range
);
MIO_EXPORT int mio_parsehttptime (
MIO_EXPORT int mio_parse_http_time_bcstr (
const mio_bch_t* str,
mio_ntime_t* nt
mio_ntime_t* nt
);
MIO_EXPORT mio_bch_t* mio_fmthttptime (
@ -201,10 +202,10 @@ MIO_EXPORT mio_bch_t* mio_fmthttptime (
);
/**
* The mio_isperencedhttpstr() function determines if the given string
* The mio_is_perenced_http_bcstr() function determines if the given string
* contains a valid percent-encoded sequence.
*/
MIO_EXPORT int mio_isperencedhttpstr (
MIO_EXPORT int mio_is_perenced_http_bcstr (
const mio_bch_t* str
);