added many new files to form fundamental base. wip
This commit is contained in:
parent
9b391741d6
commit
a6d1122e33
2
mio/configure
vendored
2
mio/configure
vendored
@ -17716,7 +17716,7 @@ fi
|
||||
|
||||
done
|
||||
|
||||
for ac_header in ifaddrs.h tiuser.h linux/netfilter_ipv4.h netinet/sctp.h
|
||||
for ac_header in ifaddrs.h tiuser.h linux/netfilter_ipv4.h netinet/in.h netinet/sctp.h
|
||||
do :
|
||||
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
||||
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
|
||||
|
@ -131,7 +131,7 @@ AC_CHECK_HEADERS([time.h sys/time.h utime.h spawn.h execinfo.h ucontext.h])
|
||||
AC_CHECK_HEADERS([sys/resource.h sys/wait.h sys/syscall.h sys/ioctl.h])
|
||||
AC_CHECK_HEADERS([sys/sendfile.h sys/epoll.h sys/event.h sys/poll.h])
|
||||
AC_CHECK_HEADERS([sys/sysctl.h sys/socket.h sys/sockio.h sys/un.h])
|
||||
AC_CHECK_HEADERS([ifaddrs.h tiuser.h linux/netfilter_ipv4.h netinet/sctp.h])
|
||||
AC_CHECK_HEADERS([ifaddrs.h tiuser.h linux/netfilter_ipv4.h netinet/in.h netinet/sctp.h])
|
||||
AC_CHECK_HEADERS([net/if.h net/if_dl.h netpacket/packet.h], [], [], [
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>])
|
||||
|
@ -24,18 +24,24 @@ include_HEADERS = \
|
||||
mio-cmn.h \
|
||||
mio-pro.h \
|
||||
mio-sck.h \
|
||||
mio-utl.h \
|
||||
mio.h
|
||||
|
||||
lib_LTLIBRARIES = libmio.la
|
||||
libmio_la_SOURCES = \
|
||||
err.c \
|
||||
logfmt.c \
|
||||
logfmtv.h \
|
||||
mio-prv.h \
|
||||
mio.c \
|
||||
mio-pro.c \
|
||||
mio-sck.c \
|
||||
mio-tim.c \
|
||||
mio-tmr.c \
|
||||
mio-utl.c \
|
||||
utf8.c
|
||||
sck-addr.c \
|
||||
sck-addr.h \
|
||||
utf8.c \
|
||||
utl.c
|
||||
libmio_la_CPPFLAGS = $(CPPFLAGS_LIB_COMMON)
|
||||
libmio_la_LDFLAGS = $(LDFLAGS_LIB_COMMON)
|
||||
libmio_la_LIBADD = $(LIBADD_LIB_COMMON) $(SSL_LIBS)
|
||||
|
@ -140,9 +140,10 @@ LTLIBRARIES = $(lib_LTLIBRARIES)
|
||||
am__DEPENDENCIES_1 =
|
||||
am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
|
||||
libmio_la_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
|
||||
am_libmio_la_OBJECTS = libmio_la-mio.lo libmio_la-mio-pro.lo \
|
||||
libmio_la-mio-sck.lo libmio_la-mio-tim.lo libmio_la-mio-tmr.lo \
|
||||
libmio_la-mio-utl.lo libmio_la-utf8.lo
|
||||
am_libmio_la_OBJECTS = libmio_la-err.lo libmio_la-logfmt.lo \
|
||||
libmio_la-mio.lo libmio_la-mio-pro.lo libmio_la-mio-sck.lo \
|
||||
libmio_la-mio-tim.lo libmio_la-mio-tmr.lo \
|
||||
libmio_la-sck-addr.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@)
|
||||
@ -392,18 +393,24 @@ include_HEADERS = \
|
||||
mio-cmn.h \
|
||||
mio-pro.h \
|
||||
mio-sck.h \
|
||||
mio-utl.h \
|
||||
mio.h
|
||||
|
||||
lib_LTLIBRARIES = libmio.la
|
||||
libmio_la_SOURCES = \
|
||||
err.c \
|
||||
logfmt.c \
|
||||
logfmtv.h \
|
||||
mio-prv.h \
|
||||
mio.c \
|
||||
mio-pro.c \
|
||||
mio-sck.c \
|
||||
mio-tim.c \
|
||||
mio-tmr.c \
|
||||
mio-utl.c \
|
||||
utf8.c
|
||||
sck-addr.c \
|
||||
sck-addr.h \
|
||||
utf8.c \
|
||||
utl.c
|
||||
|
||||
libmio_la_CPPFLAGS = $(CPPFLAGS_LIB_COMMON)
|
||||
libmio_la_LDFLAGS = $(LDFLAGS_LIB_COMMON)
|
||||
@ -559,13 +566,16 @@ mostlyclean-compile:
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmio_la-err.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmio_la-logfmt.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmio_la-mio-pro.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmio_la-mio-sck.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmio_la-mio-tim.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmio_la-mio-tmr.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmio_la-mio-utl.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmio_la-mio.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmio_la-sck-addr.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmio_la-utf8.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmio_la-utl.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mio-main.Po@am__quote@
|
||||
|
||||
.c.o:
|
||||
@ -592,6 +602,20 @@ distclean-compile:
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
|
||||
|
||||
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
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='err.c' object='libmio_la-err.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-err.lo `test -f 'err.c' || echo '$(srcdir)/'`err.c
|
||||
|
||||
libmio_la-logfmt.lo: logfmt.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-logfmt.lo -MD -MP -MF $(DEPDIR)/libmio_la-logfmt.Tpo -c -o libmio_la-logfmt.lo `test -f 'logfmt.c' || echo '$(srcdir)/'`logfmt.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmio_la-logfmt.Tpo $(DEPDIR)/libmio_la-logfmt.Plo
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='logfmt.c' object='libmio_la-logfmt.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-logfmt.lo `test -f 'logfmt.c' || echo '$(srcdir)/'`logfmt.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
|
||||
@ -627,12 +651,12 @@ libmio_la-mio-tmr.lo: mio-tmr.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-mio-tmr.lo `test -f 'mio-tmr.c' || echo '$(srcdir)/'`mio-tmr.c
|
||||
|
||||
libmio_la-mio-utl.lo: mio-utl.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-utl.lo -MD -MP -MF $(DEPDIR)/libmio_la-mio-utl.Tpo -c -o libmio_la-mio-utl.lo `test -f 'mio-utl.c' || echo '$(srcdir)/'`mio-utl.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmio_la-mio-utl.Tpo $(DEPDIR)/libmio_la-mio-utl.Plo
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mio-utl.c' object='libmio_la-mio-utl.lo' libtool=yes @AMDEPBACKSLASH@
|
||||
libmio_la-sck-addr.lo: sck-addr.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-sck-addr.lo -MD -MP -MF $(DEPDIR)/libmio_la-sck-addr.Tpo -c -o libmio_la-sck-addr.lo `test -f 'sck-addr.c' || echo '$(srcdir)/'`sck-addr.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmio_la-sck-addr.Tpo $(DEPDIR)/libmio_la-sck-addr.Plo
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sck-addr.c' object='libmio_la-sck-addr.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-mio-utl.lo `test -f 'mio-utl.c' || echo '$(srcdir)/'`mio-utl.c
|
||||
@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-sck-addr.lo `test -f 'sck-addr.c' || echo '$(srcdir)/'`sck-addr.c
|
||||
|
||||
libmio_la-utf8.lo: utf8.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-utf8.lo -MD -MP -MF $(DEPDIR)/libmio_la-utf8.Tpo -c -o libmio_la-utf8.lo `test -f 'utf8.c' || echo '$(srcdir)/'`utf8.c
|
||||
@ -641,6 +665,13 @@ libmio_la-utf8.lo: utf8.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-utf8.lo `test -f 'utf8.c' || echo '$(srcdir)/'`utf8.c
|
||||
|
||||
libmio_la-utl.lo: utl.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-utl.lo -MD -MP -MF $(DEPDIR)/libmio_la-utl.Tpo -c -o libmio_la-utl.lo `test -f 'utl.c' || echo '$(srcdir)/'`utl.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmio_la-utl.Tpo $(DEPDIR)/libmio_la-utl.Plo
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='utl.c' object='libmio_la-utl.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-utl.lo `test -f 'utl.c' || echo '$(srcdir)/'`utl.c
|
||||
|
||||
mio-main.o: main.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mio_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mio-main.o -MD -MP -MF $(DEPDIR)/mio-main.Tpo -c -o mio-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mio-main.Tpo $(DEPDIR)/mio-main.Po
|
||||
|
449
mio/lib/err.c
Normal file
449
mio/lib/err.c
Normal file
@ -0,0 +1,449 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
Copyright (c) 2015-2016 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 WAfRRANTIES
|
||||
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-prv.h"
|
||||
|
||||
static mio_ooch_t errstr_0[] = {'n','o',' ','e','r','r','o','r','\0'};
|
||||
static mio_ooch_t errstr_1[] = {'g','e','n','e','r','i','c',' ','e','r','r','o','r','\0'};
|
||||
static mio_ooch_t errstr_2[] = {'n','o','t',' ','i','m','p','l','e','m','e','n','t','e','d','\0'};
|
||||
static mio_ooch_t errstr_3[] = {'s','u','b','s','y','s','t','e','m',' ','e','r','r','o','r','\0'};
|
||||
static mio_ooch_t errstr_4[] = {'i','n','t','e','r','n','a','l',' ','e','r','r','o','r',' ','t','h','a','t',' ','s','h','o','u','l','d',' ','n','e','v','e','r',' ','h','a','v','e',' ','h','a','p','p','e','n','e','d','\0'};
|
||||
static mio_ooch_t errstr_5[] = {'i','n','s','u','f','f','i','c','i','e','n','t',' ','s','y','s','t','e','m',' ','m','e','m','o','r','y','\0'};
|
||||
static mio_ooch_t errstr_6[] = {'i','n','s','u','f','f','i','c','i','e','n','t',' ','o','b','j','e','c','t',' ','m','e','m','o','r','y','\0'};
|
||||
static mio_ooch_t errstr_7[] = {'i','n','v','a','l','i','d',' ','c','l','a','s','s','/','t','y','p','e','\0'};
|
||||
static mio_ooch_t errstr_8[] = {'i','n','v','a','l','i','d',' ','p','a','r','a','m','e','t','e','r',' ','o','r',' ','a','r','g','u','m','e','n','t','\0'};
|
||||
static mio_ooch_t errstr_9[] = {'d','a','t','a',' ','n','o','t',' ','f','o','u','n','d','\0'};
|
||||
static mio_ooch_t errstr_10[] = {'e','x','i','s','t','i','n','g','/','d','u','p','l','i','c','a','t','e',' ','d','a','t','a','\0'};
|
||||
static mio_ooch_t errstr_11[] = {'b','u','s','y','\0'};
|
||||
static mio_ooch_t errstr_12[] = {'a','c','c','e','s','s',' ','d','e','n','i','e','d','\0'};
|
||||
static mio_ooch_t errstr_13[] = {'o','p','e','r','a','t','i','o','n',' ','n','o','t',' ','p','e','r','m','i','t','t','e','d','\0'};
|
||||
static mio_ooch_t errstr_14[] = {'n','o','t',' ','a',' ','d','i','r','e','c','t','o','r','y','\0'};
|
||||
static mio_ooch_t errstr_15[] = {'i','n','t','e','r','r','u','p','t','e','d','\0'};
|
||||
static mio_ooch_t errstr_16[] = {'p','i','p','e',' ','e','r','r','o','r','\0'};
|
||||
static mio_ooch_t errstr_17[] = {'r','e','s','o','u','r','c','e',' ','t','e','m','p','o','r','a','r','i','l','y',' ','u','n','a','v','a','i','l','a','b','l','e','\0'};
|
||||
static mio_ooch_t errstr_18[] = {'b','a','d',' ','s','y','s','t','e','m',' ','h','a','n','d','l','e','\0'};
|
||||
static mio_ooch_t errstr_19[] = {'*','*','*',' ','u','n','d','e','f','i','n','e','d',' ','e','r','r','o','r',' ','*','*','*','\0'};
|
||||
static mio_ooch_t errstr_20[] = {'m','e','s','s','a','g','e',' ','r','e','c','e','i','v','e','r',' ','e','r','r','o','r','\0'};
|
||||
static mio_ooch_t errstr_21[] = {'m','e','s','s','a','g','e',' ','s','e','n','d','i','n','g',' ','e','r','r','o','r','\0'};
|
||||
static mio_ooch_t errstr_22[] = {'w','r','o','n','g',' ','n','u','m','b','e','r',' ','o','f',' ','a','r','g','u','m','e','n','t','s','\0'};
|
||||
static mio_ooch_t errstr_23[] = {'r','a','n','g','e',' ','e','r','r','o','r','\0'};
|
||||
static mio_ooch_t errstr_24[] = {'b','y','t','e','-','c','o','d','e',' ','f','u','l','l','\0'};
|
||||
static mio_ooch_t errstr_25[] = {'d','i','c','t','i','o','n','a','r','y',' ','f','u','l','l','\0'};
|
||||
static mio_ooch_t errstr_26[] = {'p','r','o','c','e','s','s','o','r',' ','f','u','l','l','\0'};
|
||||
static mio_ooch_t errstr_27[] = {'t','o','o',' ','m','a','n','y',' ','s','e','m','a','p','h','o','r','e','s','\0'};
|
||||
static mio_ooch_t errstr_28[] = {'*','*','*',' ','u','n','d','e','f','i','n','e','d',' ','e','r','r','o','r',' ','*','*','*','\0'};
|
||||
static mio_ooch_t errstr_29[] = {'d','i','v','i','d','e',' ','b','y',' ','z','e','r','o','\0'};
|
||||
static mio_ooch_t errstr_30[] = {'I','/','O',' ','e','r','r','o','r','\0'};
|
||||
static mio_ooch_t errstr_31[] = {'e','n','c','o','d','i','n','g',' ','c','o','n','v','e','r','s','i','o','n',' ','e','r','r','o','r','\0'};
|
||||
static mio_ooch_t errstr_32[] = {'i','n','s','u','f','f','i','c','i','e','n','t',' ','d','a','t','a',' ','f','o','r',' ','e','n','c','o','d','i','n','g',' ','c','o','n','v','e','r','s','i','o','n','\0'};
|
||||
static mio_ooch_t errstr_33[] = {'b','u','f','f','e','r',' ','f','u','l','l','\0'};
|
||||
static mio_ooch_t* errstr[] =
|
||||
{
|
||||
errstr_0, errstr_1, errstr_2, errstr_3, errstr_4, errstr_5, errstr_6, errstr_7,
|
||||
errstr_8, errstr_9, errstr_10, errstr_11, errstr_12, errstr_13, errstr_14, errstr_15,
|
||||
errstr_16, errstr_17, errstr_18, errstr_19, errstr_20, errstr_21, errstr_22, errstr_23,
|
||||
errstr_24, errstr_25, errstr_26, errstr_27, errstr_28, errstr_29, errstr_30, errstr_31,
|
||||
errstr_32, errstr_33
|
||||
};
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* ERROR NUMBER TO STRING CONVERSION
|
||||
* -------------------------------------------------------------------------- */
|
||||
const mio_ooch_t* mio_errnum_to_errstr (mio_errnum_t errnum)
|
||||
{
|
||||
static mio_ooch_t e_unknown[] = {'u','n','k','n','o','w','n',' ','e','r','r','o','r','\0'};
|
||||
return (errnum >= 0 && errnum < MIO_COUNTOF(errstr))? errstr[errnum]: e_unknown;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* ERROR MESSAGE CONVERSION
|
||||
* -------------------------------------------------------------------------- */
|
||||
#include <errno.h>
|
||||
|
||||
static mio_errnum_t errno_to_errnum (int errcode)
|
||||
{
|
||||
switch (errcode)
|
||||
{
|
||||
case ENOMEM: return MIO_ESYSMEM;
|
||||
case EINVAL: return MIO_EINVAL;
|
||||
|
||||
#if defined(EBUSY)
|
||||
case EBUSY: return MIO_EBUSY;
|
||||
#endif
|
||||
case EACCES: return MIO_EACCES;
|
||||
#if defined(EPERM)
|
||||
case EPERM: return MIO_EPERM;
|
||||
#endif
|
||||
#if defined(ENOTDIR)
|
||||
case ENOTDIR: return MIO_ENOTDIR;
|
||||
#endif
|
||||
case ENOENT: return MIO_ENOENT;
|
||||
#if defined(EEXIST)
|
||||
case EEXIST: return MIO_EEXIST;
|
||||
#endif
|
||||
#if defined(EINTR)
|
||||
case EINTR: return MIO_EINTR;
|
||||
#endif
|
||||
|
||||
#if defined(EPIPE)
|
||||
case EPIPE: return MIO_EPIPE;
|
||||
#endif
|
||||
|
||||
#if defined(EAGAIN) && defined(EWOULDBLOCK) && (EAGAIN != EWOULDBLOCK)
|
||||
case EAGAIN:
|
||||
case EWOULDBLOCK: return MIO_EAGAIN;
|
||||
#elif defined(EAGAIN)
|
||||
case EAGAIN: return MIO_EAGAIN;
|
||||
#elif defined(EWOULDBLOCK)
|
||||
case EWOULDBLOCK: return MIO_EAGAIN;
|
||||
#endif
|
||||
|
||||
#if defined(EBADF)
|
||||
case EBADF: return MIO_EBADHND;
|
||||
#endif
|
||||
|
||||
#if defined(EIO)
|
||||
case EIO: return MIO_EIOERR;
|
||||
#endif
|
||||
|
||||
default: return MIO_ESYSERR;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
static mio_errnum_t winerr_to_errnum (DWORD errcode)
|
||||
{
|
||||
switch (errcode)
|
||||
{
|
||||
case ERROR_NOT_ENOUGH_MEMORY:
|
||||
case ERROR_OUTOFMEMORY:
|
||||
return MIO_ESYSMEM;
|
||||
|
||||
case ERROR_INVALID_PARAMETER:
|
||||
case ERROR_INVALID_NAME:
|
||||
return MIO_EINVAL;
|
||||
|
||||
case ERROR_INVALID_HANDLE:
|
||||
return MIO_EBADHND;
|
||||
|
||||
case ERROR_ACCESS_DENIED:
|
||||
case ERROR_SHARING_VIOLATION:
|
||||
return MIO_EACCES;
|
||||
|
||||
#if defined(ERROR_IO_PRIVILEGE_FAILED)
|
||||
case ERROR_IO_PRIVILEGE_FAILED:
|
||||
#endif
|
||||
case ERROR_PRIVILEGE_NOT_HELD:
|
||||
return MIO_EPERM;
|
||||
|
||||
case ERROR_FILE_NOT_FOUND:
|
||||
case ERROR_PATH_NOT_FOUND:
|
||||
return MIO_ENOENT;
|
||||
|
||||
case ERROR_ALREADY_EXISTS:
|
||||
case ERROR_FILE_EXISTS:
|
||||
return MIO_EEXIST;
|
||||
|
||||
case ERROR_BROKEN_PIPE:
|
||||
return MIO_EPIPE;
|
||||
|
||||
default:
|
||||
return MIO_ESYSERR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__OS2__)
|
||||
static mio_errnum_t os2err_to_errnum (APIRET errcode)
|
||||
{
|
||||
/* APIRET e */
|
||||
switch (errcode)
|
||||
{
|
||||
case ERROR_NOT_ENOUGH_MEMORY:
|
||||
return MIO_ESYSMEM;
|
||||
|
||||
case ERROR_INVALID_PARAMETER:
|
||||
case ERROR_INVALID_NAME:
|
||||
return MIO_EINVAL;
|
||||
|
||||
case ERROR_INVALID_HANDLE:
|
||||
return MIO_EBADHND;
|
||||
|
||||
case ERROR_ACCESS_DENIED:
|
||||
case ERROR_SHARING_VIOLATION:
|
||||
return MIO_EACCES;
|
||||
|
||||
case ERROR_FILE_NOT_FOUND:
|
||||
case ERROR_PATH_NOT_FOUND:
|
||||
return MIO_ENOENT;
|
||||
|
||||
case ERROR_ALREADY_EXISTS:
|
||||
return MIO_EEXIST;
|
||||
|
||||
/*TODO: add more mappings */
|
||||
default:
|
||||
return MIO_ESYSERR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(macintosh)
|
||||
static mio_errnum_t macerr_to_errnum (int errcode)
|
||||
{
|
||||
switch (e)
|
||||
{
|
||||
case notEnoughMemoryErr:
|
||||
return MIO_ESYSMEM;
|
||||
case paramErr:
|
||||
return MIO_EINVAL;
|
||||
|
||||
case qErr: /* queue element not found during deletion */
|
||||
case fnfErr: /* file not found */
|
||||
case dirNFErr: /* direcotry not found */
|
||||
case resNotFound: /* resource not found */
|
||||
case resFNotFound: /* resource file not found */
|
||||
case nbpNotFound: /* name not found on remove */
|
||||
return MIO_ENOENT;
|
||||
|
||||
/*TODO: add more mappings */
|
||||
default:
|
||||
return MIO_ESYSERR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static mio_errnum_t syserrstrb (mio_t* mio, int syserr_type, int syserr_code, mio_bch_t* buf, mio_oow_t len)
|
||||
{
|
||||
switch (syserr_type)
|
||||
{
|
||||
case 1:
|
||||
#if defined(_WIN32)
|
||||
if (buf)
|
||||
{
|
||||
DWORD rc;
|
||||
rc = FormatMessageA (
|
||||
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, syserr_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
buf, len, MIO_NULL
|
||||
);
|
||||
while (rc > 0 && buf[rc - 1] == '\r' || buf[rc - 1] == '\n') buf[--rc] = '\0';
|
||||
}
|
||||
return winerr_to_errnum(syserr_code);
|
||||
#elif defined(__OS2__)
|
||||
/* TODO: convert code to string */
|
||||
if (buf) mio_copy_bcstr (buf, len, "system error");
|
||||
return os2err_to_errnum(syserr_code);
|
||||
#elif defined(macintosh)
|
||||
/* TODO: convert code to string */
|
||||
if (buf) mio_copy_bcstr (buf, len, "system error");
|
||||
return os2err_to_errnum(syserr_code);
|
||||
#else
|
||||
/* in other systems, errno is still the native system error code.
|
||||
* fall thru */
|
||||
#endif
|
||||
|
||||
case 0:
|
||||
#if defined(HAVE_STRERROR_R)
|
||||
if (buf) strerror_r (syserr_code, buf, len);
|
||||
#else
|
||||
/* this is not thread safe */
|
||||
if (buf) mio_copy_bcstr (buf, len, strerror(syserr_code));
|
||||
#endif
|
||||
return errno_to_errnum(syserr_code);
|
||||
}
|
||||
|
||||
if (buf) mio_copy_bcstr (buf, len, "system error");
|
||||
return MIO_ESYSERR;
|
||||
}
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* ERROR NUMBER/MESSAGE HANDLING
|
||||
* -------------------------------------------------------------------------- */
|
||||
const mio_ooch_t* mio_geterrstr (mio_t* mio)
|
||||
{
|
||||
return mio_errnum_to_errstr(mio->errnum);
|
||||
}
|
||||
|
||||
const mio_ooch_t* mio_geterrmsg (mio_t* mio)
|
||||
{
|
||||
if (mio->errmsg.len <= 0) return mio_errnum_to_errstr(mio->errnum);
|
||||
return mio->errmsg.buf;
|
||||
}
|
||||
|
||||
void mio_geterrinf (mio_t* mio, mio_errinf_t* info)
|
||||
{
|
||||
info->num = mio_geterrnum(mio);
|
||||
mio_copy_oocstr (info->msg, MIO_COUNTOF(info->msg), mio_geterrmsg(mio));
|
||||
}
|
||||
|
||||
const mio_ooch_t* mio_backuperrmsg (mio_t* mio)
|
||||
{
|
||||
mio_copy_oocstr (mio->errmsg.tmpbuf.ooch, MIO_COUNTOF(mio->errmsg.tmpbuf.ooch), mio_geterrmsg(mio));
|
||||
return mio->errmsg.tmpbuf.ooch;
|
||||
}
|
||||
|
||||
void mio_seterrnum (mio_t* mio, mio_errnum_t errnum)
|
||||
{
|
||||
if (mio->shuterr) return;
|
||||
mio->errnum = errnum;
|
||||
mio->errmsg.len = 0;
|
||||
}
|
||||
|
||||
void mio_seterrwithsyserr (mio_t* mio, int syserr_type, int syserr_code)
|
||||
{
|
||||
mio_errnum_t errnum;
|
||||
|
||||
if (mio->shuterr) return;
|
||||
|
||||
/*if (mio->vmprim.syserrstrb)
|
||||
{*/
|
||||
errnum = /*mio->vmprim.*/syserrstrb(mio, syserr_type, syserr_code, mio->errmsg.tmpbuf.bch, MIO_COUNTOF(mio->errmsg.tmpbuf.bch));
|
||||
mio_seterrbfmt (mio, errnum, "%hs", mio->errmsg.tmpbuf.bch);
|
||||
/*
|
||||
}
|
||||
else
|
||||
{
|
||||
MIO_ASSERT (mio, mio->vmprim.syserrstru != MIO_NULL);
|
||||
errnum = mio->vmprim.syserrstru(mio, syserr_type, syserr_code, mio->errmsg.tmpbuf.uch, MIO_COUNTOF(mio->errmsg.tmpbuf.uch));
|
||||
mio_seterrbfmt (mio, errnum, "%ls", mio->errmsg.tmpbuf.uch);
|
||||
}*/
|
||||
}
|
||||
|
||||
void mio_seterrbfmtwithsyserr (mio_t* mio, int syserr_type, int syserr_code, const mio_bch_t* fmt, ...)
|
||||
{
|
||||
mio_errnum_t errnum;
|
||||
mio_oow_t ucslen, bcslen;
|
||||
va_list ap;
|
||||
|
||||
if (mio->shuterr) return;
|
||||
|
||||
/*
|
||||
if (mio->vmprim.syserrstrb)
|
||||
{*/
|
||||
errnum = /*mio->vmprim.*/syserrstrb(mio, syserr_type, syserr_code, mio->errmsg.tmpbuf.bch, MIO_COUNTOF(mio->errmsg.tmpbuf.bch));
|
||||
|
||||
va_start (ap, fmt);
|
||||
mio_seterrbfmtv (mio, errnum, fmt, ap);
|
||||
va_end (ap);
|
||||
|
||||
if (MIO_COUNTOF(mio->errmsg.buf) - mio->errmsg.len >= 5)
|
||||
{
|
||||
mio->errmsg.buf[mio->errmsg.len++] = ' ';
|
||||
mio->errmsg.buf[mio->errmsg.len++] = '-';
|
||||
mio->errmsg.buf[mio->errmsg.len++] = ' ';
|
||||
|
||||
#if defined(MIO_OOCH_IS_BCH)
|
||||
mio->errmsg.len += mio_copy_bcstr(&mio->errmsg.buf[mio->errmsg.len], MIO_COUNTOF(mio->errmsg.buf) - mio->errmsg.len, mio->errmsg.tmpbuf.bch);
|
||||
#else
|
||||
ucslen = MIO_COUNTOF(mio->errmsg.buf) - mio->errmsg.len;
|
||||
mio_convbtoucstr (mio, mio->errmsg.tmpbuf.bch, &bcslen, &mio->errmsg.buf[mio->errmsg.len], &ucslen);
|
||||
mio->errmsg.len += ucslen;
|
||||
#endif
|
||||
}
|
||||
/*}
|
||||
else
|
||||
{
|
||||
MIO_ASSERT (mio, mio->vmprim.syserrstru != MIO_NULL);
|
||||
errnum = mio->vmprim.syserrstru(mio, syserr_type, syserr_code, mio->errmsg.tmpbuf.uch, MIO_COUNTOF(mio->errmsg.tmpbuf.uch));
|
||||
|
||||
va_start (ap, fmt);
|
||||
mio_seterrbfmtv (mio, errnum, fmt, ap);
|
||||
va_end (ap);
|
||||
|
||||
if (MIO_COUNTOF(mio->errmsg.buf) - mio->errmsg.len >= 5)
|
||||
{
|
||||
mio->errmsg.buf[mio->errmsg.len++] = ' ';
|
||||
mio->errmsg.buf[mio->errmsg.len++] = '-';
|
||||
mio->errmsg.buf[mio->errmsg.len++] = ' ';
|
||||
|
||||
#if defined(MIO_OOCH_IS_BCH)
|
||||
bcslen = MIO_COUNTOF(mio->errmsg.buf) - mio->errmsg.len;
|
||||
mio_convutobcstr (mio, mio->errmsg.tmpbuf.uch, &ucslen, &mio->errmsg.buf[mio->errmsg.len], &bcslen);
|
||||
mio->errmsg.len += bcslen;
|
||||
#else
|
||||
mio->errmsg.len += mio_copy_ucstr(&mio->errmsg.buf[mio->errmsg.len], MIO_COUNTOF(mio->errmsg.buf) - mio->errmsg.len, mio->errmsg.tmpbuf.uch);
|
||||
#endif
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
void mio_seterrufmtwithsyserr (mio_t* mio, int syserr_type, int syserr_code, const mio_uch_t* fmt, ...)
|
||||
{
|
||||
mio_errnum_t errnum;
|
||||
mio_oow_t ucslen, bcslen;
|
||||
va_list ap;
|
||||
|
||||
if (mio->shuterr) return;
|
||||
|
||||
/*if (mio->vmprim.syserrstrb)
|
||||
{*/
|
||||
errnum = /*mio->vmprim.*/syserrstrb(mio, syserr_type, syserr_code, mio->errmsg.tmpbuf.bch, MIO_COUNTOF(mio->errmsg.tmpbuf.bch));
|
||||
|
||||
va_start (ap, fmt);
|
||||
mio_seterrufmtv (mio, errnum, fmt, ap);
|
||||
va_end (ap);
|
||||
|
||||
if (MIO_COUNTOF(mio->errmsg.buf) - mio->errmsg.len >= 5)
|
||||
{
|
||||
mio->errmsg.buf[mio->errmsg.len++] = ' ';
|
||||
mio->errmsg.buf[mio->errmsg.len++] = '-';
|
||||
mio->errmsg.buf[mio->errmsg.len++] = ' ';
|
||||
|
||||
#if defined(MIO_OOCH_IS_BCH)
|
||||
mio->errmsg.len += mio_copy_bcstr(&mio->errmsg.buf[mio->errmsg.len], MIO_COUNTOF(mio->errmsg.buf) - mio->errmsg.len, mio->errmsg.tmpbuf.bch);
|
||||
#else
|
||||
ucslen = MIO_COUNTOF(mio->errmsg.buf) - mio->errmsg.len;
|
||||
mio_convbtoucstr (mio, mio->errmsg.tmpbuf.bch, &bcslen, &mio->errmsg.buf[mio->errmsg.len], &ucslen);
|
||||
mio->errmsg.len += ucslen;
|
||||
#endif
|
||||
}
|
||||
/*}
|
||||
else
|
||||
{
|
||||
MIO_ASSERT (mio, mio->vmprim.syserrstru != MIO_NULL);
|
||||
errnum = mio->vmprim.syserrstru(mio, syserr_type, syserr_code, mio->errmsg.tmpbuf.uch, MIO_COUNTOF(mio->errmsg.tmpbuf.uch));
|
||||
|
||||
va_start (ap, fmt);
|
||||
mio_seterrufmtv (mio, errnum, fmt, ap);
|
||||
va_end (ap);
|
||||
|
||||
if (MIO_COUNTOF(mio->errmsg.buf) - mio->errmsg.len >= 5)
|
||||
{
|
||||
mio->errmsg.buf[mio->errmsg.len++] = ' ';
|
||||
mio->errmsg.buf[mio->errmsg.len++] = '-';
|
||||
mio->errmsg.buf[mio->errmsg.len++] = ' ';
|
||||
|
||||
#if defined(MIO_OOCH_IS_BCH)
|
||||
bcslen = MIO_COUNTOF(mio->errmsg.buf) - mio->errmsg.len;
|
||||
mio_convutobcstr (mio, mio->errmsg.tmpbuf.uch, &ucslen, &mio->errmsg.buf[mio->errmsg.len], &bcslen);
|
||||
mio->errmsg.len += bcslen;
|
||||
#else
|
||||
mio->errmsg.len += mio_copy_ucstr(&mio->errmsg.buf[mio->errmsg.len], MIO_COUNTOF(mio->errmsg.buf) - mio->errmsg.len, mio->errmsg.tmpbuf.uch);
|
||||
#endif
|
||||
}
|
||||
}*/
|
||||
}
|
733
mio/lib/logfmt.c
Normal file
733
mio/lib/logfmt.c
Normal file
@ -0,0 +1,733 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
Copyright (c) 2015-2016 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-prv.h"
|
||||
|
||||
/*#include <stdio.h>*/ /* for snprintf(). used for floating-point number formatting */
|
||||
|
||||
#if defined(_MSC_VER) || defined(__BORLANDC__) || (defined(__WATCOMC__) && (__WATCOMC__ < 1200))
|
||||
# define snprintf _snprintf
|
||||
# if !defined(HAVE_SNPRINTF)
|
||||
# define HAVE_SNPRINTF
|
||||
# endif
|
||||
#endif
|
||||
#if defined(HAVE_QUADMATH_H)
|
||||
# include <quadmath.h> /* for quadmath_snprintf() */
|
||||
#endif
|
||||
/* TODO: remove stdio.h and quadmath.h once snprintf gets replaced by own
|
||||
floting-point conversion implementation*/
|
||||
|
||||
/* Max number conversion buffer length:
|
||||
* mio_intmax_t in base 2, plus NUL byte. */
|
||||
#define MAXNBUF (MIO_SIZEOF(mio_intmax_t) * 8 + 1)
|
||||
|
||||
enum
|
||||
{
|
||||
/* integer */
|
||||
LF_C = (1 << 0),
|
||||
LF_H = (1 << 1),
|
||||
LF_J = (1 << 2),
|
||||
LF_L = (1 << 3),
|
||||
LF_Q = (1 << 4),
|
||||
LF_T = (1 << 5),
|
||||
LF_Z = (1 << 6),
|
||||
|
||||
/* long double */
|
||||
LF_LD = (1 << 7),
|
||||
/* __float128 */
|
||||
LF_QD = (1 << 8)
|
||||
};
|
||||
|
||||
static struct
|
||||
{
|
||||
mio_uint8_t flag; /* for single occurrence */
|
||||
mio_uint8_t dflag; /* for double occurrence */
|
||||
} lm_tab[26] =
|
||||
{
|
||||
{ 0, 0 }, /* a */
|
||||
{ 0, 0 }, /* b */
|
||||
{ 0, 0 }, /* c */
|
||||
{ 0, 0 }, /* d */
|
||||
{ 0, 0 }, /* e */
|
||||
{ 0, 0 }, /* f */
|
||||
{ 0, 0 }, /* g */
|
||||
{ LF_H, LF_C }, /* h */
|
||||
{ 0, 0 }, /* i */
|
||||
{ LF_J, 0 }, /* j */
|
||||
{ 0, 0 }, /* k */
|
||||
{ LF_L, LF_Q }, /* l */
|
||||
{ 0, 0 }, /* m */
|
||||
{ 0, 0 }, /* n */
|
||||
{ 0, 0 }, /* o */
|
||||
{ 0, 0 }, /* p */
|
||||
{ LF_Q, 0 }, /* q */
|
||||
{ 0, 0 }, /* r */
|
||||
{ 0, 0 }, /* s */
|
||||
{ LF_T, 0 }, /* t */
|
||||
{ 0, 0 }, /* u */
|
||||
{ 0, 0 }, /* v */
|
||||
{ 0, 0 }, /* w */
|
||||
{ 0, 0 }, /* z */
|
||||
{ 0, 0 }, /* y */
|
||||
{ LF_Z, 0 }, /* z */
|
||||
};
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
FLAGC_DOT = (1 << 0),
|
||||
FLAGC_SPACE = (1 << 1),
|
||||
FLAGC_SHARP = (1 << 2),
|
||||
FLAGC_SIGN = (1 << 3),
|
||||
FLAGC_LEFTADJ = (1 << 4),
|
||||
FLAGC_ZEROPAD = (1 << 5),
|
||||
FLAGC_WIDTH = (1 << 6),
|
||||
FLAGC_PRECISION = (1 << 7),
|
||||
FLAGC_STAR1 = (1 << 8),
|
||||
FLAGC_STAR2 = (1 << 9),
|
||||
FLAGC_LENMOD = (1 << 10) /* length modifier */
|
||||
};
|
||||
|
||||
static const mio_bch_t hex2ascii_lower[] =
|
||||
{
|
||||
'0','1','2','3','4','5','6','7','8','9',
|
||||
'a','b','c','d','e','f','g','h','i','j','k','l','m',
|
||||
'n','o','p','q','r','s','t','u','v','w','x','y','z'
|
||||
};
|
||||
|
||||
static const mio_bch_t hex2ascii_upper[] =
|
||||
{
|
||||
'0','1','2','3','4','5','6','7','8','9',
|
||||
'A','B','C','D','E','F','G','H','I','J','K','L','M',
|
||||
'N','O','P','Q','R','S','T','U','V','W','X','H','Z'
|
||||
};
|
||||
|
||||
static mio_uch_t uch_nullstr[] = { '(','n','u','l','l', ')','\0' };
|
||||
static mio_bch_t bch_nullstr[] = { '(','n','u','l','l', ')','\0' };
|
||||
|
||||
typedef int (*mio_fmtout_putch_t) (
|
||||
mio_t* mio,
|
||||
mio_bitmask_t mask,
|
||||
mio_ooch_t c,
|
||||
mio_oow_t len
|
||||
);
|
||||
|
||||
typedef int (*mio_fmtout_putcs_t) (
|
||||
mio_t* mio,
|
||||
mio_bitmask_t mask,
|
||||
const mio_ooch_t* ptr,
|
||||
mio_oow_t len
|
||||
);
|
||||
|
||||
typedef struct mio_fmtout_t mio_fmtout_t;
|
||||
struct mio_fmtout_t
|
||||
{
|
||||
mio_oow_t count; /* out */
|
||||
mio_bitmask_t mask; /* in */
|
||||
mio_fmtout_putch_t putch; /* in */
|
||||
mio_fmtout_putcs_t putcs; /* in */
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/*
|
||||
* Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
|
||||
* order; return an optional length and a pointer to the last character
|
||||
* written in the buffer (i.e., the first character of the string).
|
||||
* The buffer pointed to by `nbuf' must have length >= MAXNBUF.
|
||||
*/
|
||||
|
||||
static mio_bch_t* sprintn_lower (mio_bch_t* nbuf, mio_uintmax_t num, int base, mio_ooi_t* lenp)
|
||||
{
|
||||
mio_bch_t* p;
|
||||
|
||||
p = nbuf;
|
||||
*p = '\0';
|
||||
do { *++p = hex2ascii_lower[num % base]; } while (num /= base);
|
||||
|
||||
if (lenp) *lenp = p - nbuf;
|
||||
return p; /* returns the end */
|
||||
}
|
||||
|
||||
static mio_bch_t* sprintn_upper (mio_bch_t* nbuf, mio_uintmax_t num, int base, mio_ooi_t* lenp)
|
||||
{
|
||||
mio_bch_t* p;
|
||||
|
||||
p = nbuf;
|
||||
*p = '\0';
|
||||
do { *++p = hex2ascii_upper[num % base]; } while (num /= base);
|
||||
|
||||
if (lenp) *lenp = p - nbuf;
|
||||
return p; /* returns the end */
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
static int put_ooch (mio_t* mio, mio_bitmask_t mask, mio_ooch_t ch, mio_oow_t len)
|
||||
{
|
||||
/* this is not equivalent to put_oocs(mio,mask,&ch, 1);
|
||||
* this function is to emit a single character multiple times */
|
||||
mio_oow_t rem;
|
||||
|
||||
if (len <= 0) return 1;
|
||||
|
||||
if (mio->log.len > 0 && mio->log.last_mask != mask)
|
||||
{
|
||||
/* the mask has changed. commit the buffered text */
|
||||
|
||||
/* TODO: HANDLE LINE ENDING CONVENTION BETTER... */
|
||||
if (mio->log.ptr[mio->log.len - 1] != '\n')
|
||||
{
|
||||
/* no line ending - append a line terminator */
|
||||
mio->log.ptr[mio->log.len++] = '\n';
|
||||
}
|
||||
vmprim_log_write (mio, mio->log.last_mask, mio->log.ptr, mio->log.len);
|
||||
mio->log.len = 0;
|
||||
}
|
||||
|
||||
redo:
|
||||
rem = 0;
|
||||
if (len > mio->log.capa - mio->log.len)
|
||||
{
|
||||
mio_oow_t newcapa, max;
|
||||
mio_ooch_t* tmp;
|
||||
|
||||
max = MIO_TYPE_MAX(mio_oow_t) - mio->log.len;
|
||||
if (len > max)
|
||||
{
|
||||
/* data too big. */
|
||||
rem += len - max;
|
||||
len = max;
|
||||
}
|
||||
|
||||
newcapa = MIO_ALIGN_POW2(mio->log.len + len, MIO_LOG_CAPA_ALIGN); /* TODO: adjust this capacity */
|
||||
if (newcapa > mio->option.log_maxcapa)
|
||||
{
|
||||
/* [NOTE]
|
||||
* it doesn't adjust newcapa to mio->option.log_maxcapa.
|
||||
* nor does it cut the input to fit it into the adjusted capacity.
|
||||
* if maxcapa set is not aligned to MIO_LOG_CAPA_ALIGN,
|
||||
* the largest buffer capacity may be suboptimal */
|
||||
goto make_do;
|
||||
}
|
||||
|
||||
/* +1 to handle line ending injection more easily */
|
||||
tmp = mio_reallocmem(mio, mio->log.ptr, (newcapa + 1) * MIO_SIZEOF(*tmp));
|
||||
if (!tmp)
|
||||
{
|
||||
make_do:
|
||||
if (mio->log.len > 0)
|
||||
{
|
||||
/* can't expand the buffer. just flush the existing contents */
|
||||
/* TODO: HANDLE LINE ENDING CONVENTION BETTER... */
|
||||
if (mio->log.ptr[mio->log.len - 1] != '\n')
|
||||
{
|
||||
/* no line ending - append a line terminator */
|
||||
mio->log.ptr[mio->log.len++] = '\n';
|
||||
}
|
||||
vmprim_log_write (mio, mio->log.last_mask, mio->log.ptr, mio->log.len);
|
||||
mio->log.len = 0;
|
||||
}
|
||||
|
||||
if (len > mio->log.capa)
|
||||
{
|
||||
rem += len - mio->log.capa;
|
||||
len = mio->log.capa;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
mio->log.ptr = tmp;
|
||||
mio->log.capa = newcapa;
|
||||
}
|
||||
}
|
||||
|
||||
while (len > 0)
|
||||
{
|
||||
mio->log.ptr[mio->log.len++] = ch;
|
||||
len--;
|
||||
}
|
||||
mio->log.last_mask = mask;
|
||||
|
||||
if (rem > 0)
|
||||
{
|
||||
len = rem;
|
||||
goto redo;
|
||||
}
|
||||
|
||||
|
||||
return 1; /* success */
|
||||
}
|
||||
|
||||
static int put_oocs (mio_t* mio, mio_bitmask_t mask, const mio_ooch_t* ptr, mio_oow_t len)
|
||||
{
|
||||
mio_oow_t rem;
|
||||
|
||||
if (len <= 0) return 1;
|
||||
|
||||
if (mio->log.len > 0 && mio->log.last_mask != mask)
|
||||
{
|
||||
/* the mask has changed. commit the buffered text */
|
||||
/* TODO: HANDLE LINE ENDING CONVENTION BETTER... */
|
||||
if (mio->log.ptr[mio->log.len - 1] != '\n')
|
||||
{
|
||||
/* no line ending - append a line terminator */
|
||||
mio->log.ptr[mio->log.len++] = '\n';
|
||||
}
|
||||
|
||||
vmprim_log_write (mio, mio->log.last_mask, mio->log.ptr, mio->log.len);
|
||||
mio->log.len = 0;
|
||||
}
|
||||
|
||||
redo:
|
||||
rem = 0;
|
||||
if (len > mio->log.capa - mio->log.len)
|
||||
{
|
||||
mio_oow_t newcapa, max;
|
||||
mio_ooch_t* tmp;
|
||||
|
||||
max = MIO_TYPE_MAX(mio_oow_t) - mio->log.len;
|
||||
if (len > max)
|
||||
{
|
||||
/* data too big. */
|
||||
rem += len - max;
|
||||
len = max;
|
||||
}
|
||||
|
||||
newcapa = MIO_ALIGN_POW2(mio->log.len + len, 512); /* TODO: adjust this capacity */
|
||||
if (newcapa > mio->option.log_maxcapa)
|
||||
{
|
||||
/* [NOTE]
|
||||
* it doesn't adjust newcapa to mio->option.log_maxcapa.
|
||||
* nor does it cut the input to fit it into the adjusted capacity.
|
||||
* if maxcapa set is not aligned to MIO_LOG_CAPA_ALIGN,
|
||||
* the largest buffer capacity may be suboptimal */
|
||||
goto make_do;
|
||||
}
|
||||
|
||||
/* +1 to handle line ending injection more easily */
|
||||
tmp = mio_reallocmem(mio, mio->log.ptr, (newcapa + 1) * MIO_SIZEOF(*tmp));
|
||||
if (!tmp)
|
||||
{
|
||||
make_do:
|
||||
if (mio->log.len > 0)
|
||||
{
|
||||
/* can't expand the buffer. just flush the existing contents */
|
||||
/* TODO: HANDLE LINE ENDING CONVENTION BETTER... */
|
||||
if (mio->log.ptr[mio->log.len - 1] != '\n')
|
||||
{
|
||||
/* no line ending - append a line terminator */
|
||||
mio->log.ptr[mio->log.len++] = '\n';
|
||||
}
|
||||
vmprim_log_write (mio, mio->log.last_mask, mio->log.ptr, mio->log.len);
|
||||
mio->log.len = 0;
|
||||
}
|
||||
|
||||
if (len > mio->log.capa)
|
||||
{
|
||||
rem += len - mio->log.capa;
|
||||
len = mio->log.capa;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mio->log.ptr = tmp;
|
||||
mio->log.capa = newcapa;
|
||||
}
|
||||
}
|
||||
|
||||
MIO_MEMCPY (&mio->log.ptr[mio->log.len], ptr, len * MIO_SIZEOF(*ptr));
|
||||
mio->log.len += len;
|
||||
mio->log.last_mask = mask;
|
||||
|
||||
if (rem > 0)
|
||||
{
|
||||
ptr += len;
|
||||
len = rem;
|
||||
goto redo;
|
||||
}
|
||||
|
||||
return 1; /* success */
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#undef FMTCHAR_IS_BCH
|
||||
#undef FMTCHAR_IS_UCH
|
||||
#undef FMTCHAR_IS_OOCH
|
||||
#undef fmtchar_t
|
||||
#undef logfmtv
|
||||
#define fmtchar_t mio_bch_t
|
||||
#define logfmtv __logbfmtv
|
||||
#define FMTCHAR_IS_BCH
|
||||
#if defined(MIO_OOCH_IS_BCH)
|
||||
# define FMTCHAR_IS_OOCH
|
||||
#endif
|
||||
#include "logfmtv.h"
|
||||
|
||||
#undef FMTCHAR_IS_BCH
|
||||
#undef FMTCHAR_IS_UCH
|
||||
#undef FMTCHAR_IS_OOCH
|
||||
#undef fmtchar_t
|
||||
#undef logfmtv
|
||||
#define fmtchar_t mio_uch_t
|
||||
#define logfmtv __logufmtv
|
||||
#define FMTCHAR_IS_UCH
|
||||
#if defined(MIO_OOCH_IS_UCH)
|
||||
# define FMTCHAR_IS_OOCH
|
||||
#endif
|
||||
#include "logfmtv.h"
|
||||
|
||||
|
||||
static int _logbfmtv (mio_t* mio, const mio_bch_t* fmt, mio_fmtout_t* data, va_list ap)
|
||||
{
|
||||
return __logbfmtv (mio, fmt, data, ap, mio_logbfmt);
|
||||
}
|
||||
|
||||
static int _logufmtv (mio_t* mio, const mio_uch_t* fmt, mio_fmtout_t* data, va_list ap)
|
||||
{
|
||||
return __logufmtv (mio, fmt, data, ap, mio_logbfmt);
|
||||
}
|
||||
|
||||
mio_ooi_t mio_logbfmt (mio_t* mio, mio_bitmask_t mask, const mio_bch_t* fmt, ...)
|
||||
{
|
||||
int x;
|
||||
va_list ap;
|
||||
mio_fmtout_t fo;
|
||||
|
||||
if (mio->log.default_type_mask & MIO_LOG_ALL_TYPES)
|
||||
{
|
||||
/* if a type is given, it's not untyped any more.
|
||||
* mask off the UNTYPED bit */
|
||||
mask &= ~MIO_LOG_UNTYPED;
|
||||
|
||||
/* if the default_type_mask has the UNTYPED bit on,
|
||||
* it'll get turned back on */
|
||||
mask |= (mio->log.default_type_mask & MIO_LOG_ALL_TYPES);
|
||||
}
|
||||
|
||||
fo.mask = mask;
|
||||
fo.putch = put_ooch;
|
||||
fo.putcs = put_oocs;
|
||||
|
||||
va_start (ap, fmt);
|
||||
x = _logbfmtv(mio, fmt, &fo, ap);
|
||||
va_end (ap);
|
||||
|
||||
if (mio->log.len > 0 && mio->log.ptr[mio->log.len - 1] == '\n')
|
||||
{
|
||||
vmprim_log_write (mio, mio->log.last_mask, mio->log.ptr, mio->log.len);
|
||||
mio->log.len = 0;
|
||||
}
|
||||
return (x <= -1)? -1: fo.count;
|
||||
}
|
||||
|
||||
mio_ooi_t mio_logufmt (mio_t* mio, mio_bitmask_t mask, const mio_uch_t* fmt, ...)
|
||||
{
|
||||
int x;
|
||||
va_list ap;
|
||||
mio_fmtout_t fo;
|
||||
|
||||
if (mio->log.default_type_mask & MIO_LOG_ALL_TYPES)
|
||||
{
|
||||
mask &= ~MIO_LOG_UNTYPED;
|
||||
mask |= (mio->log.default_type_mask & MIO_LOG_ALL_TYPES);
|
||||
}
|
||||
|
||||
fo.mask = mask;
|
||||
fo.putch = put_ooch;
|
||||
fo.putcs = put_oocs;
|
||||
|
||||
va_start (ap, fmt);
|
||||
x = _logufmtv(mio, fmt, &fo, ap);
|
||||
va_end (ap);
|
||||
|
||||
if (mio->log.len > 0 && mio->log.ptr[mio->log.len - 1] == '\n')
|
||||
{
|
||||
vmprim_log_write (mio, mio->log.last_mask, mio->log.ptr, mio->log.len);
|
||||
mio->log.len = 0;
|
||||
}
|
||||
|
||||
return (x <= -1)? -1: fo.count;
|
||||
}
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* ERROR MESSAGE FORMATTING
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
static int put_errch (mio_t* mio, mio_bitmask_t mask, mio_ooch_t ch, mio_oow_t len)
|
||||
{
|
||||
mio_oow_t max;
|
||||
|
||||
max = MIO_COUNTOF(mio->errmsg.buf) - mio->errmsg.len - 1;
|
||||
if (len > max) len = max;
|
||||
|
||||
if (len <= 0) return 1;
|
||||
|
||||
while (len > 0)
|
||||
{
|
||||
mio->errmsg.buf[mio->errmsg.len++] = ch;
|
||||
len--;
|
||||
}
|
||||
mio->errmsg.buf[mio->errmsg.len] = '\0';
|
||||
|
||||
return 1; /* success */
|
||||
}
|
||||
|
||||
static int put_errcs (mio_t* mio, mio_bitmask_t mask, const mio_ooch_t* ptr, mio_oow_t len)
|
||||
{
|
||||
mio_oow_t max;
|
||||
|
||||
max = MIO_COUNTOF(mio->errmsg.buf) - mio->errmsg.len - 1;
|
||||
if (len > max) len = max;
|
||||
|
||||
if (len <= 0) return 1;
|
||||
|
||||
MIO_MEMCPY (&mio->errmsg.buf[mio->errmsg.len], ptr, len * MIO_SIZEOF(*ptr));
|
||||
mio->errmsg.len += len;
|
||||
mio->errmsg.buf[mio->errmsg.len] = '\0';
|
||||
|
||||
return 1; /* success */
|
||||
}
|
||||
|
||||
|
||||
static mio_ooi_t __errbfmtv (mio_t* mio, mio_bitmask_t mask, const mio_bch_t* fmt, ...);
|
||||
|
||||
static int _errbfmtv (mio_t* mio, const mio_bch_t* fmt, mio_fmtout_t* data, va_list ap)
|
||||
{
|
||||
return __logbfmtv (mio, fmt, data, ap, __errbfmtv);
|
||||
}
|
||||
|
||||
static int _errufmtv (mio_t* mio, const mio_uch_t* fmt, mio_fmtout_t* data, va_list ap)
|
||||
{
|
||||
return __logufmtv (mio, fmt, data, ap, __errbfmtv);
|
||||
}
|
||||
|
||||
static mio_ooi_t __errbfmtv (mio_t* mio, mio_bitmask_t mask, const mio_bch_t* fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
mio_fmtout_t fo;
|
||||
|
||||
fo.mask = 0; /* not used */
|
||||
fo.putch = put_errch;
|
||||
fo.putcs = put_errcs;
|
||||
|
||||
va_start (ap, fmt);
|
||||
_errbfmtv (mio, fmt, &fo, ap);
|
||||
va_end (ap);
|
||||
|
||||
return fo.count;
|
||||
}
|
||||
|
||||
void mio_seterrbfmt (mio_t* mio, mio_errnum_t errnum, const mio_bch_t* fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
mio_fmtout_t fo;
|
||||
|
||||
if (mio->shuterr) return;
|
||||
mio->errmsg.len = 0;
|
||||
|
||||
fo.mask = 0; /* not used */
|
||||
fo.putch = put_errch;
|
||||
fo.putcs = put_errcs;
|
||||
|
||||
va_start (ap, fmt);
|
||||
_errbfmtv (mio, fmt, &fo, ap);
|
||||
va_end (ap);
|
||||
|
||||
mio->errnum = errnum;
|
||||
}
|
||||
|
||||
void mio_seterrufmt (mio_t* mio, mio_errnum_t errnum, const mio_uch_t* fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
mio_fmtout_t fo;
|
||||
|
||||
if (mio->shuterr) return;
|
||||
mio->errmsg.len = 0;
|
||||
|
||||
fo.mask = 0; /* not used */
|
||||
fo.putch = put_errch;
|
||||
fo.putcs = put_errcs;
|
||||
|
||||
va_start (ap, fmt);
|
||||
_errufmtv (mio, fmt, &fo, ap);
|
||||
va_end (ap);
|
||||
|
||||
mio->errnum = errnum;
|
||||
}
|
||||
|
||||
|
||||
void mio_seterrbfmtv (mio_t* mio, mio_errnum_t errnum, const mio_bch_t* fmt, va_list ap)
|
||||
{
|
||||
mio_fmtout_t fo;
|
||||
|
||||
if (mio->shuterr) return;
|
||||
|
||||
mio->errmsg.len = 0;
|
||||
|
||||
fo.mask = 0; /* not used */
|
||||
fo.putch = put_errch;
|
||||
fo.putcs = put_errcs;
|
||||
|
||||
_errbfmtv (mio, fmt, &fo, ap);
|
||||
mio->errnum = errnum;
|
||||
}
|
||||
|
||||
void mio_seterrufmtv (mio_t* mio, mio_errnum_t errnum, const mio_uch_t* fmt, va_list ap)
|
||||
{
|
||||
mio_fmtout_t fo;
|
||||
|
||||
if (mio->shuterr) return;
|
||||
|
||||
mio->errmsg.len = 0;
|
||||
|
||||
fo.mask = 0; /* not used */
|
||||
fo.putch = put_errch;
|
||||
fo.putcs = put_errcs;
|
||||
|
||||
_errufmtv (mio, fmt, &fo, ap);
|
||||
mio->errnum = errnum;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* SUPPORT FOR THE BUILTIN SPRINTF PRIMITIVE FUNCTION
|
||||
* -------------------------------------------------------------------------- */
|
||||
static int put_sprcs (mio_t* mio, mio_bitmask_t mask, const mio_ooch_t* ptr, mio_oow_t len)
|
||||
{
|
||||
if (len > mio->sprintf.xbuf.capa - mio->sprintf.xbuf.len)
|
||||
{
|
||||
mio_ooch_t* tmp;
|
||||
mio_oow_t newcapa;
|
||||
|
||||
newcapa = mio->sprintf.xbuf.len + len + 1;
|
||||
newcapa = MIO_ALIGN_POW2(newcapa, 256);
|
||||
|
||||
tmp = (mio_ooch_t*)mio_reallocmem(mio, mio->sprintf.xbuf.ptr, newcapa * MIO_SIZEOF(*tmp));
|
||||
if (!tmp) return -1;
|
||||
|
||||
mio->sprintf.xbuf.ptr = tmp;
|
||||
mio->sprintf.xbuf.capa = newcapa;
|
||||
}
|
||||
|
||||
MIO_MEMCPY (&mio->sprintf.xbuf.ptr[mio->sprintf.xbuf.len], ptr, len * MIO_SIZEOF(*ptr));
|
||||
mio->sprintf.xbuf.len += len;
|
||||
return 1; /* success */
|
||||
}
|
||||
|
||||
static int put_sprch (mio_t* mio, mio_bitmask_t mask, mio_ooch_t ch, mio_oow_t len)
|
||||
{
|
||||
if (len > mio->sprintf.xbuf.capa - mio->sprintf.xbuf.len)
|
||||
{
|
||||
mio_ooch_t* tmp;
|
||||
mio_oow_t newcapa;
|
||||
|
||||
newcapa = mio->sprintf.xbuf.len + len + 1;
|
||||
newcapa = MIO_ALIGN_POW2(newcapa, 256);
|
||||
|
||||
tmp = (mio_ooch_t*)mio_reallocmem(mio, mio->sprintf.xbuf.ptr, newcapa * MIO_SIZEOF(*tmp));
|
||||
if (!tmp) return -1;
|
||||
|
||||
mio->sprintf.xbuf.ptr = tmp;
|
||||
mio->sprintf.xbuf.capa = newcapa;
|
||||
}
|
||||
|
||||
while (len > 0)
|
||||
{
|
||||
--len;
|
||||
mio->sprintf.xbuf.ptr[mio->sprintf.xbuf.len++] = ch;
|
||||
}
|
||||
|
||||
return 1; /* success */
|
||||
}
|
||||
|
||||
static mio_ooi_t __sprbfmtv (mio_t* mio, mio_bitmask_t mask, const mio_bch_t* fmt, ...);
|
||||
|
||||
static int _sprbfmtv (mio_t* mio, const mio_bch_t* fmt, mio_fmtout_t* data, va_list ap)
|
||||
{
|
||||
return __logbfmtv (mio, fmt, data, ap, __sprbfmtv);
|
||||
}
|
||||
|
||||
/*
|
||||
static int _sprufmtv (mio_t* mio, const mio_uch_t* fmt, mio_fmtout_t* data, va_list ap)
|
||||
{
|
||||
return __logufmtv (mio, fmt, data, ap, __sprbfmtv);
|
||||
}*/
|
||||
|
||||
static mio_ooi_t __sprbfmtv (mio_t* mio, mio_bitmask_t mask, const mio_bch_t* fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
mio_fmtout_t fo;
|
||||
|
||||
fo.mask = mask; /* not used */
|
||||
fo.putch = put_sprch;
|
||||
fo.putcs = put_sprcs;
|
||||
|
||||
va_start (ap, fmt);
|
||||
_sprbfmtv (mio, fmt, &fo, ap);
|
||||
va_end (ap);
|
||||
|
||||
return fo.count;
|
||||
}
|
||||
|
||||
mio_ooi_t mio_sproutbfmt (mio_t* mio, mio_bitmask_t mask, const mio_bch_t* fmt, ...)
|
||||
{
|
||||
int x;
|
||||
va_list ap;
|
||||
mio_fmtout_t fo;
|
||||
|
||||
fo.mask = mask;
|
||||
fo.putch = put_sprch;
|
||||
fo.putcs = put_sprcs;
|
||||
|
||||
va_start (ap, fmt);
|
||||
x = _sprbfmtv(mio, fmt, &fo, ap);
|
||||
va_end (ap);
|
||||
|
||||
return (x <= -1)? -1: fo.count;
|
||||
}
|
||||
|
||||
/*
|
||||
mio_ooi_t mio_sproutufmt (mio_t* mio, mio_bitmask_t mask, const mio_uch_t* fmt, ...)
|
||||
{
|
||||
int x;
|
||||
va_list ap;
|
||||
mio_fmtout_t fo;
|
||||
|
||||
fo.mask = mask;
|
||||
fo.putch = put_sprch;
|
||||
fo.putcs = put_sprcs;
|
||||
|
||||
va_start (ap, fmt);
|
||||
x = _sprufmtv (mio, fmt, &fo, ap);
|
||||
va_end (ap);
|
||||
|
||||
return (x <= -1)? -1: fo.count;
|
||||
}*/
|
||||
|
996
mio/lib/logfmtv.h
Normal file
996
mio/lib/logfmtv.h
Normal file
@ -0,0 +1,996 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
Copyright (c) 2015-2016 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains a formatted output routine derived from kvprintf()
|
||||
* of FreeBSD. It has been heavily modified and bug-fixed.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1986, 1988, 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
* (c) UNIX System Laboratories, Inc.
|
||||
* All or some portions of this file are derived from material licensed
|
||||
* to the University of California by American Telephone and Telegraph
|
||||
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
|
||||
* the permission of UNIX System Laboratories, Inc.
|
||||
*
|
||||
* 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.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* NOTE: data output is aborted if the data limit is reached or
|
||||
* I/O error occurs */
|
||||
|
||||
#undef PUT_OOCH
|
||||
#undef PUT_OOCS
|
||||
|
||||
#define PUT_OOCH(c,n) do { \
|
||||
if (n > 0) { \
|
||||
int xx; \
|
||||
if ((xx = data->putch (mio, data->mask, c, n)) <= -1) goto oops; \
|
||||
if (xx == 0) goto done; \
|
||||
data->count += n; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define PUT_OOCS(ptr,len) do { \
|
||||
if (len > 0) { \
|
||||
int xx; \
|
||||
if ((xx = data->putcs (mio, data->mask, ptr, len)) <= -1) goto oops; \
|
||||
if (xx == 0) goto done; \
|
||||
data->count += len; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static int logfmtv (mio_t* mio, const fmtchar_t* fmt, mio_fmtout_t* data, va_list ap, outbfmt_t outbfmt)
|
||||
{
|
||||
const fmtchar_t* percent;
|
||||
const fmtchar_t* checkpoint;
|
||||
mio_bch_t nbuf[MAXNBUF], bch;
|
||||
const mio_bch_t* nbufp;
|
||||
int n, base, neg, sign;
|
||||
mio_ooi_t tmp, width, precision;
|
||||
mio_ooch_t ch, padc;
|
||||
#if !defined(FMTCHAR_IS_OOCH)
|
||||
fmtchar_t fch;
|
||||
#endif
|
||||
int lm_flag, lm_dflag, flagc, numlen;
|
||||
mio_uintmax_t num = 0;
|
||||
int stop = 0;
|
||||
|
||||
#if 0
|
||||
mio_bchbuf_t* fltfmt;
|
||||
mio_oochbuf_t* fltout;
|
||||
#endif
|
||||
mio_bch_t* (*sprintn) (mio_bch_t* nbuf, mio_uintmax_t num, int base, mio_ooi_t* lenp);
|
||||
|
||||
data->count = 0;
|
||||
|
||||
#if 0
|
||||
fltfmt = &mio->d->fltfmt;
|
||||
fltout = &mio->d->fltout;
|
||||
|
||||
fltfmt->ptr = fltfmt->buf;
|
||||
fltfmt->capa = MIO_COUNTOF(fltfmt->buf) - 1;
|
||||
|
||||
fltout->ptr = fltout->buf;
|
||||
fltout->capa = MIO_COUNTOF(fltout->buf) - 1;
|
||||
#endif
|
||||
|
||||
while (1)
|
||||
{
|
||||
#if defined(FMTCHAR_IS_OOCH)
|
||||
checkpoint = fmt;
|
||||
while ((ch = *fmt++) != '%' || stop)
|
||||
{
|
||||
if (ch == '\0')
|
||||
{
|
||||
PUT_OOCS (checkpoint, fmt - checkpoint - 1);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
PUT_OOCS (checkpoint, fmt - checkpoint - 1);
|
||||
#else
|
||||
#if defined(MIO_OOCH_IS_UCH)
|
||||
/* fmtchar is bch. ooch is uch. convert bch to uch */
|
||||
checkpoint = fmt;
|
||||
while ((fch = *fmt++) != '%' || stop)
|
||||
{
|
||||
if (fch == '\0') break;
|
||||
}
|
||||
while (checkpoint < fmt - 1)
|
||||
{
|
||||
mio_oow_t cvlen, bclen;
|
||||
bclen = fmt - checkpoint - 1;
|
||||
cvlen = mio->cmgr->bctouc(checkpoint, bclen, &ch);
|
||||
if (cvlen == 0 || cvlen > bclen) goto oops;
|
||||
checkpoint += cvlen;
|
||||
PUT_OOCH (ch, 1);
|
||||
}
|
||||
if (fch == '\0') goto done;
|
||||
#else
|
||||
while ((fch = *fmt++) != '%' || stop)
|
||||
{
|
||||
mio_bch_t bcsbuf[MIO_MBLEN_MAX + 1];
|
||||
mio_oow_t ucslen, bcslen;
|
||||
|
||||
if (fch == '\0') goto done;
|
||||
|
||||
/* fmtchar is uch. ooch is bch. convert uch to bch */
|
||||
ucslen = 1;
|
||||
bcslen = MIO_COUNTOF(bcsbuf);
|
||||
if (mio_conv_uchars_to_bchars_with_cmgr(&fch, &ucslen, bcsbuf, &bcslen, mio->cmgr) <= -1) goto oops;
|
||||
PUT_OOCS (bcsbuf, bcslen);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
percent = fmt - 1;
|
||||
|
||||
padc = ' ';
|
||||
width = 0; precision = 0;
|
||||
neg = 0; sign = 0;
|
||||
|
||||
lm_flag = 0; lm_dflag = 0; flagc = 0;
|
||||
sprintn = sprintn_lower;
|
||||
|
||||
reswitch:
|
||||
switch (ch = *fmt++)
|
||||
{
|
||||
case '%': /* %% */
|
||||
bch = ch;
|
||||
goto print_lowercase_c;
|
||||
|
||||
/* flag characters */
|
||||
case '.':
|
||||
if (flagc & FLAGC_DOT) goto invalid_format;
|
||||
flagc |= FLAGC_DOT;
|
||||
goto reswitch;
|
||||
|
||||
case '#':
|
||||
if (flagc & (FLAGC_WIDTH | FLAGC_DOT | FLAGC_LENMOD)) goto invalid_format;
|
||||
flagc |= FLAGC_SHARP;
|
||||
goto reswitch;
|
||||
|
||||
case ' ':
|
||||
if (flagc & (FLAGC_WIDTH | FLAGC_DOT | FLAGC_LENMOD)) goto invalid_format;
|
||||
flagc |= FLAGC_SPACE;
|
||||
goto reswitch;
|
||||
|
||||
case '+': /* place sign for signed conversion */
|
||||
if (flagc & (FLAGC_WIDTH | FLAGC_DOT | FLAGC_LENMOD)) goto invalid_format;
|
||||
flagc |= FLAGC_SIGN;
|
||||
goto reswitch;
|
||||
|
||||
case '-': /* left adjusted */
|
||||
if (flagc & (FLAGC_WIDTH | FLAGC_DOT | FLAGC_LENMOD)) goto invalid_format;
|
||||
if (flagc & FLAGC_DOT)
|
||||
{
|
||||
goto invalid_format;
|
||||
}
|
||||
else
|
||||
{
|
||||
flagc |= FLAGC_LEFTADJ;
|
||||
if (flagc & FLAGC_ZEROPAD)
|
||||
{
|
||||
padc = ' ';
|
||||
flagc &= ~FLAGC_ZEROPAD;
|
||||
}
|
||||
}
|
||||
|
||||
goto reswitch;
|
||||
|
||||
case '*': /* take the length from the parameter */
|
||||
if (flagc & FLAGC_DOT)
|
||||
{
|
||||
if (flagc & (FLAGC_STAR2 | FLAGC_PRECISION)) goto invalid_format;
|
||||
flagc |= FLAGC_STAR2;
|
||||
|
||||
precision = va_arg(ap, mio_ooi_t); /* this deviates from the standard printf that accepts 'int' */
|
||||
if (precision < 0)
|
||||
{
|
||||
/* if precision is less than 0,
|
||||
* treat it as if no .precision is specified */
|
||||
flagc &= ~FLAGC_DOT;
|
||||
precision = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (flagc & (FLAGC_STAR1 | FLAGC_WIDTH)) goto invalid_format;
|
||||
flagc |= FLAGC_STAR1;
|
||||
|
||||
width = va_arg(ap, mio_ooi_t); /* it deviates from the standard printf that accepts 'int' */
|
||||
if (width < 0)
|
||||
{
|
||||
/*
|
||||
if (flagc & FLAGC_LEFTADJ)
|
||||
flagc &= ~FLAGC_LEFTADJ;
|
||||
else
|
||||
*/
|
||||
flagc |= FLAGC_LEFTADJ;
|
||||
width = -width;
|
||||
}
|
||||
}
|
||||
goto reswitch;
|
||||
|
||||
case '0': /* zero pad */
|
||||
if (flagc & FLAGC_LENMOD) goto invalid_format;
|
||||
if (!(flagc & (FLAGC_DOT | FLAGC_LEFTADJ)))
|
||||
{
|
||||
padc = '0';
|
||||
flagc |= FLAGC_ZEROPAD;
|
||||
goto reswitch;
|
||||
}
|
||||
/* end of flags characters */
|
||||
|
||||
case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
if (flagc & FLAGC_LENMOD) goto invalid_format;
|
||||
for (n = 0;; ++fmt)
|
||||
{
|
||||
n = n * 10 + ch - '0';
|
||||
ch = *fmt;
|
||||
if (ch < '0' || ch > '9') break;
|
||||
}
|
||||
if (flagc & FLAGC_DOT)
|
||||
{
|
||||
if (flagc & FLAGC_STAR2) goto invalid_format;
|
||||
precision = n;
|
||||
flagc |= FLAGC_PRECISION;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (flagc & FLAGC_STAR1) goto invalid_format;
|
||||
width = n;
|
||||
flagc |= FLAGC_WIDTH;
|
||||
}
|
||||
goto reswitch;
|
||||
|
||||
/* length modifiers */
|
||||
case 'h': /* short int */
|
||||
case 'l': /* long int */
|
||||
case 'q': /* long long int */
|
||||
case 'j': /* mio_intmax_t/mio_uintmax_t */
|
||||
case 'z': /* mio_ooi_t/mio_oow_t */
|
||||
case 't': /* ptrdiff_t */
|
||||
if (lm_flag & (LF_LD | LF_QD)) goto invalid_format;
|
||||
|
||||
flagc |= FLAGC_LENMOD;
|
||||
if (lm_dflag)
|
||||
{
|
||||
/* error */
|
||||
goto invalid_format;
|
||||
}
|
||||
else if (lm_flag)
|
||||
{
|
||||
if (lm_tab[ch - 'a'].dflag && lm_flag == lm_tab[ch - 'a'].flag)
|
||||
{
|
||||
lm_flag &= ~lm_tab[ch - 'a'].flag;
|
||||
lm_flag |= lm_tab[ch - 'a'].dflag;
|
||||
lm_dflag |= lm_flag;
|
||||
goto reswitch;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* error */
|
||||
goto invalid_format;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lm_flag |= lm_tab[ch - 'a'].flag;
|
||||
goto reswitch;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'L': /* long double */
|
||||
if (flagc & FLAGC_LENMOD)
|
||||
{
|
||||
/* conflict with other length modifier */
|
||||
goto invalid_format;
|
||||
}
|
||||
flagc |= FLAGC_LENMOD;
|
||||
lm_flag |= LF_LD;
|
||||
goto reswitch;
|
||||
|
||||
case 'Q': /* __float128 */
|
||||
if (flagc & FLAGC_LENMOD)
|
||||
{
|
||||
/* conflict with other length modifier */
|
||||
goto invalid_format;
|
||||
}
|
||||
flagc |= FLAGC_LENMOD;
|
||||
lm_flag |= LF_QD;
|
||||
goto reswitch;
|
||||
/* end of length modifiers */
|
||||
|
||||
case 'n': /* number of characters printed so far */
|
||||
if (lm_flag & LF_J) /* j */
|
||||
*(va_arg(ap, mio_intmax_t*)) = data->count;
|
||||
else if (lm_flag & LF_Z) /* z */
|
||||
*(va_arg(ap, mio_ooi_t*)) = data->count;
|
||||
#if (MIO_SIZEOF_LONG_LONG > 0)
|
||||
else if (lm_flag & LF_Q) /* ll */
|
||||
*(va_arg(ap, long long int*)) = data->count;
|
||||
#endif
|
||||
else if (lm_flag & LF_L) /* l */
|
||||
*(va_arg(ap, long int*)) = data->count;
|
||||
else if (lm_flag & LF_H) /* h */
|
||||
*(va_arg(ap, short int*)) = data->count;
|
||||
else if (lm_flag & LF_C) /* hh */
|
||||
*(va_arg(ap, char*)) = data->count;
|
||||
else if (flagc & FLAGC_LENMOD)
|
||||
goto invalid_format;
|
||||
else
|
||||
*(va_arg(ap, int*)) = data->count;
|
||||
break;
|
||||
|
||||
/* signed integer conversions */
|
||||
case 'd':
|
||||
case 'i': /* signed conversion */
|
||||
base = 10;
|
||||
sign = 1;
|
||||
goto handle_sign;
|
||||
/* end of signed integer conversions */
|
||||
|
||||
/* unsigned integer conversions */
|
||||
case 'o':
|
||||
base = 8;
|
||||
goto handle_nosign;
|
||||
case 'u':
|
||||
base = 10;
|
||||
goto handle_nosign;
|
||||
case 'X':
|
||||
sprintn = sprintn_upper;
|
||||
case 'x':
|
||||
base = 16;
|
||||
goto handle_nosign;
|
||||
case 'b':
|
||||
base = 2;
|
||||
goto handle_nosign;
|
||||
/* end of unsigned integer conversions */
|
||||
|
||||
case 'p': /* pointer */
|
||||
base = 16;
|
||||
|
||||
if (width == 0) flagc |= FLAGC_SHARP;
|
||||
else flagc &= ~FLAGC_SHARP;
|
||||
|
||||
num = (mio_uintptr_t)va_arg(ap, void*);
|
||||
goto number;
|
||||
|
||||
case 'c':
|
||||
{
|
||||
/* zeropad must not take effect for 'c' */
|
||||
if (flagc & FLAGC_ZEROPAD) padc = ' ';
|
||||
if (lm_flag & LF_L) goto uppercase_c;
|
||||
#if defined(MIO_OOCH_IS_UCH)
|
||||
if (lm_flag & LF_J) goto uppercase_c;
|
||||
#endif
|
||||
lowercase_c:
|
||||
bch = MIO_SIZEOF(mio_bch_t) < MIO_SIZEOF(int)? va_arg(ap, int): va_arg(ap, mio_bch_t);
|
||||
|
||||
print_lowercase_c:
|
||||
/* precision 0 doesn't kill the letter */
|
||||
width--;
|
||||
if (!(flagc & FLAGC_LEFTADJ) && width > 0) PUT_OOCH (padc, width);
|
||||
PUT_OOCH (bch, 1);
|
||||
if ((flagc & FLAGC_LEFTADJ) && width > 0) PUT_OOCH (padc, width);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'C':
|
||||
{
|
||||
mio_uch_t ooch;
|
||||
|
||||
/* zeropad must not take effect for 'C' */
|
||||
if (flagc & FLAGC_ZEROPAD) padc = ' ';
|
||||
if (lm_flag & LF_H) goto lowercase_c;
|
||||
#if defined(MIO_OOCH_IS_BCH)
|
||||
if (lm_flag & LF_J) goto lowercase_c;
|
||||
#endif
|
||||
uppercase_c:
|
||||
ooch = MIO_SIZEOF(mio_uch_t) < MIO_SIZEOF(int)? va_arg(ap, int): va_arg(ap, mio_uch_t);
|
||||
|
||||
/* precision 0 doesn't kill the letter */
|
||||
width--;
|
||||
if (!(flagc & FLAGC_LEFTADJ) && width > 0) PUT_OOCH (padc, width);
|
||||
PUT_OOCH (ooch, 1);
|
||||
if ((flagc & FLAGC_LEFTADJ) && width > 0) PUT_OOCH (padc, width);
|
||||
break;
|
||||
}
|
||||
|
||||
case 's':
|
||||
{
|
||||
const mio_bch_t* bsp;
|
||||
mio_oow_t bslen, slen;
|
||||
|
||||
/* zeropad must not take effect for 'S' */
|
||||
if (flagc & FLAGC_ZEROPAD) padc = ' ';
|
||||
if (lm_flag & LF_L) goto uppercase_s;
|
||||
#if defined(MIO_OOCH_IS_UCH)
|
||||
if (lm_flag & LF_J) goto uppercase_s;
|
||||
#endif
|
||||
lowercase_s:
|
||||
|
||||
bsp = va_arg (ap, mio_bch_t*);
|
||||
if (bsp == MIO_NULL) bsp = bch_nullstr;
|
||||
|
||||
#if defined(MIO_OOCH_IS_UCH)
|
||||
/* get the length */
|
||||
for (bslen = 0; bsp[bslen]; bslen++);
|
||||
|
||||
if (mio_conv_bchars_to_uchars_with_cmgr(bsp, &bslen, MIO_NULL, &slen, mio->cmgr, 0) <= -1) goto oops;
|
||||
|
||||
/* slen holds the length after conversion */
|
||||
n = slen;
|
||||
if ((flagc & FLAGC_DOT) && precision < slen) n = precision;
|
||||
width -= n;
|
||||
|
||||
if (!(flagc & FLAGC_LEFTADJ) && width > 0) PUT_OOCH (padc, width);
|
||||
|
||||
{
|
||||
mio_ooch_t conv_buf[32];
|
||||
mio_oow_t conv_len, src_len, tot_len = 0;
|
||||
while (n > 0)
|
||||
{
|
||||
MIO_ASSERT (mio, bslen > tot_len);
|
||||
|
||||
src_len = bslen - tot_len;
|
||||
conv_len = MIO_COUNTOF(conv_buf);
|
||||
|
||||
/* this must not fail since the dry-run above was successful */
|
||||
mio_conv_bchars_to_uchars_with_cmgr(&bsp[tot_len], &src_len, conv_buf, &conv_len, mio->cmgr, 0);
|
||||
tot_len += src_len;
|
||||
|
||||
if (conv_len > n) conv_len = n;
|
||||
PUT_OOCS (conv_buf, conv_len);
|
||||
|
||||
n -= conv_len;
|
||||
}
|
||||
}
|
||||
|
||||
if ((flagc & FLAGC_LEFTADJ) && width > 0) PUT_OOCH (padc, width);
|
||||
#else
|
||||
if (flagc & FLAGC_DOT)
|
||||
{
|
||||
for (n = 0; n < precision && bsp[n]; n++);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (n = 0; bsp[n]; n++);
|
||||
}
|
||||
|
||||
width -= n;
|
||||
|
||||
if (!(flagc & FLAGC_LEFTADJ) && width > 0) PUT_OOCH (padc, width);
|
||||
PUT_OOCS (bsp, n);
|
||||
if ((flagc & FLAGC_LEFTADJ) && width > 0) PUT_OOCH (padc, width);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
case 'S':
|
||||
{
|
||||
const mio_uch_t* usp;
|
||||
mio_oow_t uslen, slen;
|
||||
|
||||
/* zeropad must not take effect for 's' */
|
||||
if (flagc & FLAGC_ZEROPAD) padc = ' ';
|
||||
if (lm_flag & LF_H) goto lowercase_s;
|
||||
#if defined(MIO_OOCH_IS_UCH)
|
||||
if (lm_flag & LF_J) goto lowercase_s;
|
||||
#endif
|
||||
uppercase_s:
|
||||
usp = va_arg (ap, mio_uch_t*);
|
||||
if (usp == MIO_NULL) usp = uch_nullstr;
|
||||
|
||||
#if defined(MIO_OOCH_IS_BCH)
|
||||
/* get the length */
|
||||
for (uslen = 0; usp[uslen]; uslen++);
|
||||
|
||||
if (mio_conv_uchars_to_bchars_with_cmgr(usp, &uslen, MIO_NULL, &slen, mio->cmgr) <= -1) goto oops;
|
||||
|
||||
/* slen holds the length after conversion */
|
||||
n = slen;
|
||||
if ((flagc & FLAGC_DOT) && precision < slen) n = precision;
|
||||
width -= n;
|
||||
|
||||
if (!(flagc & FLAGC_LEFTADJ) && width > 0) PUT_OOCH (padc, width);
|
||||
{
|
||||
mio_ooch_t conv_buf[32];
|
||||
mio_oow_t conv_len, src_len, tot_len = 0;
|
||||
while (n > 0)
|
||||
{
|
||||
MIO_ASSERT (mio, uslen > tot_len);
|
||||
|
||||
src_len = uslen - tot_len;
|
||||
conv_len = MIO_COUNTOF(conv_buf);
|
||||
|
||||
/* this must not fail since the dry-run above was successful */
|
||||
mio_conv_uchars_to_bchars_with_cmgr (&usp[tot_len], &src_len, conv_buf, &conv_len, mio->cmgr);
|
||||
tot_len += src_len;
|
||||
|
||||
if (conv_len > n) conv_len = n;
|
||||
PUT_OOCS (conv_buf, conv_len);
|
||||
|
||||
n -= conv_len;
|
||||
}
|
||||
}
|
||||
if ((flagc & FLAGC_LEFTADJ) && width > 0) PUT_OOCH (padc, width);
|
||||
#else
|
||||
if (flagc & FLAGC_DOT)
|
||||
{
|
||||
for (n = 0; n < precision && usp[n]; n++);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (n = 0; usp[n]; n++);
|
||||
}
|
||||
|
||||
width -= n;
|
||||
|
||||
if (!(flagc & FLAGC_LEFTADJ) && width > 0) PUT_OOCH (padc, width);
|
||||
PUT_OOCS (usp, n);
|
||||
if ((flagc & FLAGC_LEFTADJ) && width > 0) PUT_OOCH (padc, width);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
case 'O': /* object - ignore precision, width, adjustment */
|
||||
if (print_object(mio, data->mask, va_arg(ap, mio_oop_t), outbfmt) <= -1) goto oops;
|
||||
break;
|
||||
|
||||
#if 0
|
||||
case 'e':
|
||||
case 'E':
|
||||
case 'f':
|
||||
case 'F':
|
||||
case 'g':
|
||||
case 'G':
|
||||
/*
|
||||
case 'a':
|
||||
case 'A':
|
||||
*/
|
||||
{
|
||||
/* let me rely on snprintf until i implement float-point to string conversion */
|
||||
int q;
|
||||
mio_oow_t fmtlen;
|
||||
#if (MIO_SIZEOF___FLOAT128 > 0) && defined(HAVE_QUADMATH_SNPRINTF)
|
||||
__float128 v_qd;
|
||||
#endif
|
||||
long double v_ld;
|
||||
double v_d;
|
||||
int dtype = 0;
|
||||
mio_oow_t newcapa;
|
||||
|
||||
if (lm_flag & LF_J)
|
||||
{
|
||||
#if (MIO_SIZEOF___FLOAT128 > 0) && defined(HAVE_QUADMATH_SNPRINTF) && (MIO_SIZEOF_FLTMAX_T == MIO_SIZEOF___FLOAT128)
|
||||
v_qd = va_arg (ap, mio_fltmax_t);
|
||||
dtype = LF_QD;
|
||||
#elif MIO_SIZEOF_FLTMAX_T == MIO_SIZEOF_DOUBLE
|
||||
v_d = va_arg (ap, mio_fltmax_t);
|
||||
#elif MIO_SIZEOF_FLTMAX_T == MIO_SIZEOF_LONG_DOUBLE
|
||||
v_ld = va_arg (ap, mio_fltmax_t);
|
||||
dtype = LF_LD;
|
||||
#else
|
||||
#error Unsupported mio_flt_t
|
||||
#endif
|
||||
}
|
||||
else if (lm_flag & LF_Z)
|
||||
{
|
||||
/* mio_flt_t is limited to double or long double */
|
||||
|
||||
/* precedence goes to double if sizeof(double) == sizeof(long double)
|
||||
* for example, %Lf didn't work on some old platforms.
|
||||
* so i prefer the format specifier with no modifier.
|
||||
*/
|
||||
#if MIO_SIZEOF_FLT_T == MIO_SIZEOF_DOUBLE
|
||||
v_d = va_arg (ap, mio_flt_t);
|
||||
#elif MIO_SIZEOF_FLT_T == MIO_SIZEOF_LONG_DOUBLE
|
||||
v_ld = va_arg (ap, mio_flt_t);
|
||||
dtype = LF_LD;
|
||||
#else
|
||||
#error Unsupported mio_flt_t
|
||||
#endif
|
||||
}
|
||||
else if (lm_flag & (LF_LD | LF_L))
|
||||
{
|
||||
v_ld = va_arg (ap, long double);
|
||||
dtype = LF_LD;
|
||||
}
|
||||
#if (MIO_SIZEOF___FLOAT128 > 0) && defined(HAVE_QUADMATH_SNPRINTF)
|
||||
else if (lm_flag & (LF_QD | LF_Q))
|
||||
{
|
||||
v_qd = va_arg (ap, __float128);
|
||||
dtype = LF_QD;
|
||||
}
|
||||
#endif
|
||||
else if (flagc & FLAGC_LENMOD)
|
||||
{
|
||||
goto invalid_format;
|
||||
}
|
||||
else
|
||||
{
|
||||
v_d = va_arg (ap, double);
|
||||
}
|
||||
|
||||
fmtlen = fmt - percent;
|
||||
if (fmtlen > fltfmt->capa)
|
||||
{
|
||||
if (fltfmt->ptr == fltfmt->buf)
|
||||
{
|
||||
fltfmt->ptr = MIO_MMGR_ALLOC (MIO_MMGR_GETDFL(), MIO_SIZEOF(*fltfmt->ptr) * (fmtlen + 1));
|
||||
if (fltfmt->ptr == MIO_NULL) goto oops;
|
||||
}
|
||||
else
|
||||
{
|
||||
mio_mchar_t* tmpptr;
|
||||
|
||||
tmpptr = MIO_MMGR_REALLOC (MIO_MMGR_GETDFL(), fltfmt->ptr, MIO_SIZEOF(*fltfmt->ptr) * (fmtlen + 1));
|
||||
if (tmpptr == MIO_NULL) goto oops;
|
||||
fltfmt->ptr = tmpptr;
|
||||
}
|
||||
|
||||
fltfmt->capa = fmtlen;
|
||||
}
|
||||
|
||||
/* compose back the format specifier */
|
||||
fmtlen = 0;
|
||||
fltfmt->ptr[fmtlen++] = '%';
|
||||
if (flagc & FLAGC_SPACE) fltfmt->ptr[fmtlen++] = ' ';
|
||||
if (flagc & FLAGC_SHARP) fltfmt->ptr[fmtlen++] = '#';
|
||||
if (flagc & FLAGC_SIGN) fltfmt->ptr[fmtlen++] = '+';
|
||||
if (flagc & FLAGC_LEFTADJ) fltfmt->ptr[fmtlen++] = '-';
|
||||
if (flagc & FLAGC_ZEROPAD) fltfmt->ptr[fmtlen++] = '0';
|
||||
|
||||
if (flagc & FLAGC_STAR1) fltfmt->ptr[fmtlen++] = '*';
|
||||
else if (flagc & FLAGC_WIDTH)
|
||||
{
|
||||
fmtlen += mio_fmtuintmaxtombs (
|
||||
&fltfmt->ptr[fmtlen], fltfmt->capa - fmtlen,
|
||||
width, 10, -1, '\0', MIO_NULL);
|
||||
}
|
||||
if (flagc & FLAGC_DOT) fltfmt->ptr[fmtlen++] = '.';
|
||||
if (flagc & FLAGC_STAR2) fltfmt->ptr[fmtlen++] = '*';
|
||||
else if (flagc & FLAGC_PRECISION)
|
||||
{
|
||||
fmtlen += mio_fmtuintmaxtombs (
|
||||
&fltfmt->ptr[fmtlen], fltfmt->capa - fmtlen,
|
||||
precision, 10, -1, '\0', MIO_NULL);
|
||||
}
|
||||
|
||||
if (dtype == LF_LD)
|
||||
fltfmt->ptr[fmtlen++] = 'L';
|
||||
#if (MIO_SIZEOF___FLOAT128 > 0)
|
||||
else if (dtype == LF_QD)
|
||||
fltfmt->ptr[fmtlen++] = 'Q';
|
||||
#endif
|
||||
|
||||
fltfmt->ptr[fmtlen++] = ch;
|
||||
fltfmt->ptr[fmtlen] = '\0';
|
||||
|
||||
#if defined(HAVE_SNPRINTF)
|
||||
/* nothing special here */
|
||||
#else
|
||||
/* best effort to avoid buffer overflow when no snprintf is available.
|
||||
* i really can't do much if it happens. */
|
||||
newcapa = precision + width + 32;
|
||||
if (fltout->capa < newcapa)
|
||||
{
|
||||
MIO_ASSERT (mio, fltout->ptr == fltout->buf);
|
||||
|
||||
fltout->ptr = MIO_MMGR_ALLOC (MIO_MMGR_GETDFL(), MIO_SIZEOF(char_t) * (newcapa + 1));
|
||||
if (fltout->ptr == MIO_NULL) goto oops;
|
||||
fltout->capa = newcapa;
|
||||
}
|
||||
#endif
|
||||
|
||||
while (1)
|
||||
{
|
||||
|
||||
if (dtype == LF_LD)
|
||||
{
|
||||
#if defined(HAVE_SNPRINTF)
|
||||
q = snprintf ((mio_mchar_t*)fltout->ptr, fltout->capa + 1, fltfmt->ptr, v_ld);
|
||||
#else
|
||||
q = sprintf ((mio_mchar_t*)fltout->ptr, fltfmt->ptr, v_ld);
|
||||
#endif
|
||||
}
|
||||
#if (MIO_SIZEOF___FLOAT128 > 0) && defined(HAVE_QUADMATH_SNPRINTF)
|
||||
else if (dtype == LF_QD)
|
||||
{
|
||||
q = quadmath_snprintf ((mio_mchar_t*)fltout->ptr, fltout->capa + 1, fltfmt->ptr, v_qd);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
#if defined(HAVE_SNPRINTF)
|
||||
q = snprintf ((mio_mchar_t*)fltout->ptr, fltout->capa + 1, fltfmt->ptr, v_d);
|
||||
#else
|
||||
q = sprintf ((mio_mchar_t*)fltout->ptr, fltfmt->ptr, v_d);
|
||||
#endif
|
||||
}
|
||||
if (q <= -1) goto oops;
|
||||
if (q <= fltout->capa) break;
|
||||
|
||||
newcapa = fltout->capa * 2;
|
||||
if (newcapa < q) newcapa = q;
|
||||
|
||||
if (fltout->ptr == fltout->sbuf)
|
||||
{
|
||||
fltout->ptr = MIO_MMGR_ALLOC (MIO_MMGR_GETDFL(), MIO_SIZEOF(char_t) * (newcapa + 1));
|
||||
if (fltout->ptr == MIO_NULL) goto oops;
|
||||
}
|
||||
else
|
||||
{
|
||||
char_t* tmpptr;
|
||||
|
||||
tmpptr = MIO_MMGR_REALLOC (MIO_MMGR_GETDFL(), fltout->ptr, MIO_SIZEOF(char_t) * (newcapa + 1));
|
||||
if (tmpptr == MIO_NULL) goto oops;
|
||||
fltout->ptr = tmpptr;
|
||||
}
|
||||
fltout->capa = newcapa;
|
||||
}
|
||||
|
||||
if (MIO_SIZEOF(char_t) != MIO_SIZEOF(mio_mchar_t))
|
||||
{
|
||||
fltout->ptr[q] = '\0';
|
||||
while (q > 0)
|
||||
{
|
||||
q--;
|
||||
fltout->ptr[q] = ((mio_mchar_t*)fltout->ptr)[q];
|
||||
}
|
||||
}
|
||||
|
||||
sp = fltout->ptr;
|
||||
flagc &= ~FLAGC_DOT;
|
||||
width = 0;
|
||||
precision = 0;
|
||||
goto print_lowercase_s;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
handle_nosign:
|
||||
sign = 0;
|
||||
if (lm_flag & LF_J)
|
||||
{
|
||||
#if defined(__GNUC__) && \
|
||||
(MIO_SIZEOF_UINTMAX_T > MIO_SIZEOF_OOW_T) && \
|
||||
(MIO_SIZEOF_UINTMAX_T != MIO_SIZEOF_LONG_LONG) && \
|
||||
(MIO_SIZEOF_UINTMAX_T != MIO_SIZEOF_LONG)
|
||||
/* GCC-compiled binaries crashed when getting mio_uintmax_t with va_arg.
|
||||
* This is just a work-around for it */
|
||||
int i;
|
||||
for (i = 0, num = 0; i < MIO_SIZEOF(mio_uintmax_t) / MIO_SIZEOF(mio_oow_t); i++)
|
||||
{
|
||||
#if defined(MIO_ENDIAN_BIG)
|
||||
num = num << (8 * MIO_SIZEOF(mio_oow_t)) | (va_arg (ap, mio_oow_t));
|
||||
#else
|
||||
register int shift = i * MIO_SIZEOF(mio_oow_t);
|
||||
mio_oow_t x = va_arg (ap, mio_oow_t);
|
||||
num |= (mio_uintmax_t)x << (shift * 8);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
num = va_arg (ap, mio_uintmax_t);
|
||||
#endif
|
||||
}
|
||||
#if 0
|
||||
else if (lm_flag & LF_T)
|
||||
num = va_arg (ap, mio_ptrdiff_t);
|
||||
#endif
|
||||
else if (lm_flag & LF_Z)
|
||||
num = va_arg (ap, mio_oow_t);
|
||||
#if (MIO_SIZEOF_LONG_LONG > 0)
|
||||
else if (lm_flag & LF_Q)
|
||||
num = va_arg (ap, unsigned long long int);
|
||||
#endif
|
||||
else if (lm_flag & (LF_L | LF_LD))
|
||||
num = va_arg (ap, unsigned long int);
|
||||
else if (lm_flag & LF_H)
|
||||
num = (unsigned short int)va_arg (ap, int);
|
||||
else if (lm_flag & LF_C)
|
||||
num = (unsigned char)va_arg (ap, int);
|
||||
else
|
||||
num = va_arg (ap, unsigned int);
|
||||
goto number;
|
||||
|
||||
handle_sign:
|
||||
if (lm_flag & LF_J)
|
||||
{
|
||||
#if defined(__GNUC__) && \
|
||||
(MIO_SIZEOF_INTMAX_T > MIO_SIZEOF_OOI_T) && \
|
||||
(MIO_SIZEOF_UINTMAX_T != MIO_SIZEOF_LONG_LONG) && \
|
||||
(MIO_SIZEOF_UINTMAX_T != MIO_SIZEOF_LONG)
|
||||
/* GCC-compiled binraries crashed when getting mio_uintmax_t with va_arg.
|
||||
* This is just a work-around for it */
|
||||
int i;
|
||||
for (i = 0, num = 0; i < MIO_SIZEOF(mio_intmax_t) / MIO_SIZEOF(mio_oow_t); i++)
|
||||
{
|
||||
#if defined(MIO_ENDIAN_BIG)
|
||||
num = num << (8 * MIO_SIZEOF(mio_oow_t)) | (va_arg (ap, mio_oow_t));
|
||||
#else
|
||||
register int shift = i * MIO_SIZEOF(mio_oow_t);
|
||||
mio_oow_t x = va_arg (ap, mio_oow_t);
|
||||
num |= (mio_uintmax_t)x << (shift * 8);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
num = va_arg (ap, mio_intmax_t);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
else if (lm_flag & LF_T)
|
||||
num = va_arg(ap, mio_ptrdiff_t);
|
||||
#endif
|
||||
else if (lm_flag & LF_Z)
|
||||
num = va_arg (ap, mio_ooi_t);
|
||||
#if (MIO_SIZEOF_LONG_LONG > 0)
|
||||
else if (lm_flag & LF_Q)
|
||||
num = va_arg (ap, long long int);
|
||||
#endif
|
||||
else if (lm_flag & (LF_L | LF_LD))
|
||||
num = va_arg (ap, long int);
|
||||
else if (lm_flag & LF_H)
|
||||
num = (short int)va_arg (ap, int);
|
||||
else if (lm_flag & LF_C)
|
||||
num = (char)va_arg (ap, int);
|
||||
else
|
||||
num = va_arg (ap, int);
|
||||
|
||||
number:
|
||||
if (sign && (mio_intmax_t)num < 0)
|
||||
{
|
||||
neg = 1;
|
||||
num = -(mio_intmax_t)num;
|
||||
}
|
||||
|
||||
nbufp = sprintn (nbuf, num, base, &tmp);
|
||||
if ((flagc & FLAGC_SHARP) && num != 0)
|
||||
{
|
||||
if (base == 2 || base == 8) tmp += 2;
|
||||
else if (base == 16) tmp += 3;
|
||||
}
|
||||
if (neg) tmp++;
|
||||
else if (flagc & FLAGC_SIGN) tmp++;
|
||||
else if (flagc & FLAGC_SPACE) tmp++;
|
||||
|
||||
numlen = (int)((const mio_bch_t*)nbufp - (const mio_bch_t*)nbuf);
|
||||
if ((flagc & FLAGC_DOT) && precision > numlen)
|
||||
{
|
||||
/* extra zeros for precision specified */
|
||||
tmp += (precision - numlen);
|
||||
}
|
||||
|
||||
if (!(flagc & FLAGC_LEFTADJ) && !(flagc & FLAGC_ZEROPAD) && width > 0 && (width -= tmp) > 0)
|
||||
{
|
||||
PUT_OOCH (padc, width);
|
||||
width = 0;
|
||||
}
|
||||
|
||||
if (neg) PUT_OOCH ('-', 1);
|
||||
else if (flagc & FLAGC_SIGN) PUT_OOCH ('+', 1);
|
||||
else if (flagc & FLAGC_SPACE) PUT_OOCH (' ', 1);
|
||||
|
||||
if ((flagc & FLAGC_SHARP) && num != 0)
|
||||
{
|
||||
if (base == 2)
|
||||
{
|
||||
PUT_OOCH ('2', 1);
|
||||
PUT_OOCH ('r', 1);
|
||||
}
|
||||
if (base == 8)
|
||||
{
|
||||
PUT_OOCH ('8', 1);
|
||||
PUT_OOCH ('r', 1);
|
||||
}
|
||||
else if (base == 16)
|
||||
{
|
||||
PUT_OOCH ('1', 1);
|
||||
PUT_OOCH ('6', 1);
|
||||
PUT_OOCH ('r', 1);
|
||||
}
|
||||
}
|
||||
|
||||
if ((flagc & FLAGC_DOT) && precision > numlen)
|
||||
{
|
||||
/* extra zeros for precision specified */
|
||||
PUT_OOCH ('0', precision - numlen);
|
||||
}
|
||||
|
||||
if (!(flagc & FLAGC_LEFTADJ) && width > 0 && (width -= tmp) > 0)
|
||||
{
|
||||
PUT_OOCH (padc, width);
|
||||
}
|
||||
|
||||
while (*nbufp) PUT_OOCH (*nbufp--, 1); /* output actual digits */
|
||||
|
||||
if ((flagc & FLAGC_LEFTADJ) && width > 0 && (width -= tmp) > 0)
|
||||
{
|
||||
PUT_OOCH (padc, width);
|
||||
}
|
||||
break;
|
||||
|
||||
invalid_format:
|
||||
#if defined(FMTCHAR_IS_OOCH)
|
||||
PUT_OOCS (percent, fmt - percent);
|
||||
#else
|
||||
while (percent < fmt) PUT_OOCH (*percent++, 1);
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
#if defined(FMTCHAR_IS_OOCH)
|
||||
PUT_OOCS (percent, fmt - percent);
|
||||
#else
|
||||
while (percent < fmt) PUT_OOCH (*percent++, 1);
|
||||
#endif
|
||||
/*
|
||||
* Since we ignore an formatting argument it is no
|
||||
* longer safe to obey the remaining formatting
|
||||
* arguments as the arguments will no longer match
|
||||
* the format specs.
|
||||
*/
|
||||
stop = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
return 0;
|
||||
|
||||
oops:
|
||||
return -1;
|
||||
}
|
||||
#undef PUT_OOCH
|
@ -26,6 +26,7 @@
|
||||
|
||||
|
||||
#include <mio.h>
|
||||
#include <mio-utl.h>
|
||||
#include <mio-sck.h>
|
||||
#include <mio-pro.h>
|
||||
|
||||
|
@ -340,6 +340,9 @@
|
||||
/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
|
||||
#undef HAVE_NDIR_H
|
||||
|
||||
/* Define to 1 if you have the <netinet/in.h> header file. */
|
||||
#undef HAVE_NETINET_IN_H
|
||||
|
||||
/* Define to 1 if you have the <netinet/sctp.h> header file. */
|
||||
#undef HAVE_NETINET_SCTP_H
|
||||
|
||||
|
@ -107,7 +107,7 @@ static int make_param (mio_t* mio, const mio_bch_t* cmd, int flags, param_t* par
|
||||
param->argv = MIO_MMGR_ALLOC (mio->mmgr, (fcnt + 1) * MIO_SIZEOF(argv[0]));
|
||||
if (param->argv == MIO_NULL)
|
||||
{
|
||||
mio->errnum = MIO_ENOMEM;
|
||||
mio->errnum = MIO_ESYSMEM;
|
||||
goto oops;
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,9 @@
|
||||
#define _MIO_PRV_H_
|
||||
|
||||
#include "mio.h"
|
||||
#include "mio-utl.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
|
||||
/*TODO: redefine and remove these */
|
||||
#include <assert.h>
|
||||
@ -40,58 +43,6 @@
|
||||
#define MIO_MEMCMP(dst,src,count) memcmp(dst,src,count)
|
||||
#define MIO_ASSERT assert
|
||||
|
||||
#define MIO_CWQFL_SIZE 16
|
||||
#define MIO_CWQFL_ALIGN 16
|
||||
|
||||
typedef struct mio_mux_t mio_mux_t;
|
||||
|
||||
struct mio_t
|
||||
{
|
||||
mio_mmgr_t* mmgr;
|
||||
mio_errnum_t errnum;
|
||||
mio_stopreq_t stopreq; /* stop request to abort mio_loop() */
|
||||
|
||||
struct
|
||||
{
|
||||
mio_dev_t* head;
|
||||
mio_dev_t* tail;
|
||||
} actdev; /* active devices */
|
||||
|
||||
struct
|
||||
{
|
||||
mio_dev_t* head;
|
||||
mio_dev_t* tail;
|
||||
} hltdev; /* halted devices */
|
||||
|
||||
struct
|
||||
{
|
||||
mio_dev_t* head;
|
||||
mio_dev_t* tail;
|
||||
} zmbdev; /* zombie devices */
|
||||
|
||||
mio_uint8_t bigbuf[65535]; /* TODO: make this dynamic depending on devices added. device may indicate a buffer size required??? */
|
||||
|
||||
unsigned int renew_watch: 1;
|
||||
unsigned int in_exec: 1;
|
||||
|
||||
struct
|
||||
{
|
||||
mio_oow_t capa;
|
||||
mio_oow_t size;
|
||||
mio_tmrjob_t* jobs;
|
||||
} tmr;
|
||||
|
||||
mio_cwq_t cwq;
|
||||
mio_cwq_t* cwqfl[MIO_CWQFL_SIZE]; /* list of free cwq objects */
|
||||
|
||||
/* platform specific fields below */
|
||||
#if defined(_WIN32)
|
||||
HANDLE iocp;
|
||||
#else
|
||||
mio_mux_t* mux;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
#define MIO_EPOCH_YEAR (1970)
|
||||
#define MIO_EPOCH_MON (1)
|
||||
|
@ -142,7 +142,7 @@ mio_tmridx_t mio_instmrjob (mio_t* mio, const mio_tmrjob_t* job)
|
||||
tmp = (mio_tmrjob_t*)MIO_MMGR_REALLOC (mio->mmgr, mio->tmr.jobs, new_capa * MIO_SIZEOF(*tmp));
|
||||
if (tmp == MIO_NULL)
|
||||
{
|
||||
mio->errnum = MIO_ENOMEM;
|
||||
mio->errnum = MIO_ESYSMEM;
|
||||
return MIO_TMRIDX_INVALID;
|
||||
}
|
||||
|
||||
|
@ -1,526 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
Copyright (c) 2015-2016 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 WAfRRANTIES
|
||||
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-prv.h"
|
||||
|
||||
|
||||
/* ========================================================================= */
|
||||
|
||||
#if defined(MIO_HAVE_UINT16_T)
|
||||
|
||||
mio_uint16_t mio_ntoh16 (mio_uint16_t x)
|
||||
{
|
||||
#if defined(MIO_ENDIAN_BIG)
|
||||
return x;
|
||||
#elif defined(MIO_ENDIAN_LITTLE)
|
||||
mio_uint8_t* c = (mio_uint8_t*)&x;
|
||||
return (mio_uint16_t)(
|
||||
((mio_uint16_t)c[0] << 8) |
|
||||
((mio_uint16_t)c[1] << 0));
|
||||
#else
|
||||
# error Unknown endian
|
||||
#endif
|
||||
}
|
||||
|
||||
mio_uint16_t mio_hton16 (mio_uint16_t x)
|
||||
{
|
||||
#if defined(MIO_ENDIAN_BIG)
|
||||
return x;
|
||||
#elif defined(MIO_ENDIAN_LITTLE)
|
||||
mio_uint8_t* c = (mio_uint8_t*)&x;
|
||||
return (mio_uint16_t)(
|
||||
((mio_uint16_t)c[0] << 8) |
|
||||
((mio_uint16_t)c[1] << 0));
|
||||
#else
|
||||
# error Unknown endian
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ========================================================================= */
|
||||
|
||||
#if defined(MIO_HAVE_UINT32_T)
|
||||
|
||||
mio_uint32_t mio_ntoh32 (mio_uint32_t x)
|
||||
{
|
||||
#if defined(MIO_ENDIAN_BIG)
|
||||
return x;
|
||||
#elif defined(MIO_ENDIAN_LITTLE)
|
||||
mio_uint8_t* c = (mio_uint8_t*)&x;
|
||||
return (mio_uint32_t)(
|
||||
((mio_uint32_t)c[0] << 24) |
|
||||
((mio_uint32_t)c[1] << 16) |
|
||||
((mio_uint32_t)c[2] << 8) |
|
||||
((mio_uint32_t)c[3] << 0));
|
||||
#else
|
||||
# error Unknown endian
|
||||
#endif
|
||||
}
|
||||
|
||||
mio_uint32_t mio_hton32 (mio_uint32_t x)
|
||||
{
|
||||
#if defined(MIO_ENDIAN_BIG)
|
||||
return x;
|
||||
#elif defined(MIO_ENDIAN_LITTLE)
|
||||
mio_uint8_t* c = (mio_uint8_t*)&x;
|
||||
return (mio_uint32_t)(
|
||||
((mio_uint32_t)c[0] << 24) |
|
||||
((mio_uint32_t)c[1] << 16) |
|
||||
((mio_uint32_t)c[2] << 8) |
|
||||
((mio_uint32_t)c[3] << 0));
|
||||
#else
|
||||
# error Unknown endian
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ========================================================================= */
|
||||
|
||||
#if defined(MIO_HAVE_UINT64_T)
|
||||
|
||||
mio_uint64_t mio_ntoh64 (mio_uint64_t x)
|
||||
{
|
||||
#if defined(MIO_ENDIAN_BIG)
|
||||
return x;
|
||||
#elif defined(MIO_ENDIAN_LITTLE)
|
||||
mio_uint8_t* c = (mio_uint8_t*)&x;
|
||||
return (mio_uint64_t)(
|
||||
((mio_uint64_t)c[0] << 56) |
|
||||
((mio_uint64_t)c[1] << 48) |
|
||||
((mio_uint64_t)c[2] << 40) |
|
||||
((mio_uint64_t)c[3] << 32) |
|
||||
((mio_uint64_t)c[4] << 24) |
|
||||
((mio_uint64_t)c[5] << 16) |
|
||||
((mio_uint64_t)c[6] << 8) |
|
||||
((mio_uint64_t)c[7] << 0));
|
||||
#else
|
||||
# error Unknown endian
|
||||
#endif
|
||||
}
|
||||
|
||||
mio_uint64_t mio_hton64 (mio_uint64_t x)
|
||||
{
|
||||
#if defined(MIO_ENDIAN_BIG)
|
||||
return x;
|
||||
#elif defined(MIO_ENDIAN_LITTLE)
|
||||
mio_uint8_t* c = (mio_uint8_t*)&x;
|
||||
return (mio_uint64_t)(
|
||||
((mio_uint64_t)c[0] << 56) |
|
||||
((mio_uint64_t)c[1] << 48) |
|
||||
((mio_uint64_t)c[2] << 40) |
|
||||
((mio_uint64_t)c[3] << 32) |
|
||||
((mio_uint64_t)c[4] << 24) |
|
||||
((mio_uint64_t)c[5] << 16) |
|
||||
((mio_uint64_t)c[6] << 8) |
|
||||
((mio_uint64_t)c[7] << 0));
|
||||
#else
|
||||
# error Unknown endian
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ========================================================================= */
|
||||
|
||||
#if defined(MIO_HAVE_UINT128_T)
|
||||
|
||||
mio_uint128_t mio_ntoh128 (mio_uint128_t x)
|
||||
{
|
||||
#if defined(MIO_ENDIAN_BIG)
|
||||
return x;
|
||||
#elif defined(MIO_ENDIAN_LITTLE)
|
||||
mio_uint8_t* c = (mio_uint8_t*)&x;
|
||||
return (mio_uint128_t)(
|
||||
((mio_uint128_t)c[0] << 120) |
|
||||
((mio_uint128_t)c[1] << 112) |
|
||||
((mio_uint128_t)c[2] << 104) |
|
||||
((mio_uint128_t)c[3] << 96) |
|
||||
((mio_uint128_t)c[4] << 88) |
|
||||
((mio_uint128_t)c[5] << 80) |
|
||||
((mio_uint128_t)c[6] << 72) |
|
||||
((mio_uint128_t)c[7] << 64) |
|
||||
((mio_uint128_t)c[8] << 56) |
|
||||
((mio_uint128_t)c[9] << 48) |
|
||||
((mio_uint128_t)c[10] << 40) |
|
||||
((mio_uint128_t)c[11] << 32) |
|
||||
((mio_uint128_t)c[12] << 24) |
|
||||
((mio_uint128_t)c[13] << 16) |
|
||||
((mio_uint128_t)c[14] << 8) |
|
||||
((mio_uint128_t)c[15] << 0));
|
||||
#else
|
||||
# error Unknown endian
|
||||
#endif
|
||||
}
|
||||
|
||||
mio_uint128_t mio_hton128 (mio_uint128_t x)
|
||||
{
|
||||
#if defined(MIO_ENDIAN_BIG)
|
||||
return x;
|
||||
#elif defined(MIO_ENDIAN_LITTLE)
|
||||
mio_uint8_t* c = (mio_uint8_t*)&x;
|
||||
return (mio_uint128_t)(
|
||||
((mio_uint128_t)c[0] << 120) |
|
||||
((mio_uint128_t)c[1] << 112) |
|
||||
((mio_uint128_t)c[2] << 104) |
|
||||
((mio_uint128_t)c[3] << 96) |
|
||||
((mio_uint128_t)c[4] << 88) |
|
||||
((mio_uint128_t)c[5] << 80) |
|
||||
((mio_uint128_t)c[6] << 72) |
|
||||
((mio_uint128_t)c[7] << 64) |
|
||||
((mio_uint128_t)c[8] << 56) |
|
||||
((mio_uint128_t)c[9] << 48) |
|
||||
((mio_uint128_t)c[10] << 40) |
|
||||
((mio_uint128_t)c[11] << 32) |
|
||||
((mio_uint128_t)c[12] << 24) |
|
||||
((mio_uint128_t)c[13] << 16) |
|
||||
((mio_uint128_t)c[14] << 8) |
|
||||
((mio_uint128_t)c[15] << 0));
|
||||
#else
|
||||
# error Unknown endian
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ========================================================================= */
|
||||
|
||||
#define MIO_MT(x) (x)
|
||||
#define IS_MSPACE(x) ((x) == MIO_MT(' ') || (x) == MIO_MT('\t') || (x) == MIO_MT('\n') || (x) == MIO_MT('\r'))
|
||||
|
||||
mio_bch_t* mio_mbsdup (mio_t* mio, const mio_bch_t* src)
|
||||
{
|
||||
mio_bch_t* dst;
|
||||
mio_oow_t len;
|
||||
|
||||
dst = (mio_bch_t*)src;
|
||||
while (*dst != MIO_MT('\0')) dst++;
|
||||
len = dst - src;
|
||||
|
||||
dst = MIO_MMGR_ALLOC (mio->mmgr, (len + 1) * MIO_SIZEOF(*src));
|
||||
if (!dst)
|
||||
{
|
||||
mio->errnum = MIO_ENOMEM;
|
||||
return MIO_NULL;
|
||||
}
|
||||
|
||||
MIO_MEMCPY (dst, src, (len + 1) * MIO_SIZEOF(*src));
|
||||
return dst;
|
||||
}
|
||||
|
||||
mio_oow_t mio_mbscpy (mio_bch_t* buf, const mio_bch_t* str)
|
||||
{
|
||||
mio_bch_t* org = buf;
|
||||
while ((*buf++ = *str++) != MIO_MT('\0'));
|
||||
return buf - org - 1;
|
||||
}
|
||||
|
||||
int mio_mbsspltrn (
|
||||
mio_bch_t* s, const mio_bch_t* delim,
|
||||
mio_bch_t lquote, mio_bch_t rquote,
|
||||
mio_bch_t escape, const mio_bch_t* trset)
|
||||
{
|
||||
mio_bch_t* p = s, *d;
|
||||
mio_bch_t* sp = MIO_NULL, * ep = MIO_NULL;
|
||||
int delim_mode;
|
||||
int cnt = 0;
|
||||
|
||||
if (delim == MIO_NULL) delim_mode = 0;
|
||||
else
|
||||
{
|
||||
delim_mode = 1;
|
||||
for (d = (mio_bch_t*)delim; *d != MIO_MT('\0'); d++)
|
||||
if (!IS_MSPACE(*d)) delim_mode = 2;
|
||||
}
|
||||
|
||||
if (delim_mode == 0)
|
||||
{
|
||||
/* skip preceding space characters */
|
||||
while (IS_MSPACE(*p)) p++;
|
||||
|
||||
/* when 0 is given as "delim", it has an effect of cutting
|
||||
preceding and trailing space characters off "s". */
|
||||
if (lquote != MIO_MT('\0') && *p == lquote)
|
||||
{
|
||||
mio_mbscpy (p, p + 1);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (*p == MIO_MT('\0')) return -1;
|
||||
|
||||
if (escape != MIO_MT('\0') && *p == escape)
|
||||
{
|
||||
if (trset != MIO_NULL && p[1] != MIO_MT('\0'))
|
||||
{
|
||||
const mio_bch_t* ep = trset;
|
||||
while (*ep != MIO_MT('\0'))
|
||||
{
|
||||
if (p[1] == *ep++)
|
||||
{
|
||||
p[1] = *ep;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mio_mbscpy (p, p + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*p == rquote)
|
||||
{
|
||||
p++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (sp == 0) sp = p;
|
||||
ep = p;
|
||||
p++;
|
||||
}
|
||||
while (IS_MSPACE(*p)) p++;
|
||||
if (*p != MIO_MT('\0')) return -1;
|
||||
|
||||
if (sp == 0 && ep == 0) s[0] = MIO_MT('\0');
|
||||
else
|
||||
{
|
||||
ep[1] = MIO_MT('\0');
|
||||
if (s != (mio_bch_t*)sp) mio_mbscpy (s, sp);
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (*p)
|
||||
{
|
||||
if (!IS_MSPACE(*p))
|
||||
{
|
||||
if (sp == 0) sp = p;
|
||||
ep = p;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
if (sp == 0 && ep == 0) s[0] = MIO_MT('\0');
|
||||
else
|
||||
{
|
||||
ep[1] = MIO_MT('\0');
|
||||
if (s != (mio_bch_t*)sp) mio_mbscpy (s, sp);
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (delim_mode == 1)
|
||||
{
|
||||
mio_bch_t* o;
|
||||
|
||||
while (*p)
|
||||
{
|
||||
o = p;
|
||||
while (IS_MSPACE(*p)) p++;
|
||||
if (o != p) { mio_mbscpy (o, p); p = o; }
|
||||
|
||||
if (lquote != MIO_MT('\0') && *p == lquote)
|
||||
{
|
||||
mio_mbscpy (p, p + 1);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (*p == MIO_MT('\0')) return -1;
|
||||
|
||||
if (escape != MIO_MT('\0') && *p == escape)
|
||||
{
|
||||
if (trset != MIO_NULL && p[1] != MIO_MT('\0'))
|
||||
{
|
||||
const mio_bch_t* ep = trset;
|
||||
while (*ep != MIO_MT('\0'))
|
||||
{
|
||||
if (p[1] == *ep++)
|
||||
{
|
||||
p[1] = *ep;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
mio_mbscpy (p, p + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*p == rquote)
|
||||
{
|
||||
*p++ = MIO_MT('\0');
|
||||
cnt++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
o = p;
|
||||
for (;;)
|
||||
{
|
||||
if (*p == MIO_MT('\0'))
|
||||
{
|
||||
if (o != p) cnt++;
|
||||
break;
|
||||
}
|
||||
if (IS_MSPACE (*p))
|
||||
{
|
||||
*p++ = MIO_MT('\0');
|
||||
cnt++;
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* if (delim_mode == 2) */
|
||||
{
|
||||
mio_bch_t* o;
|
||||
int ok;
|
||||
|
||||
while (*p != MIO_MT('\0'))
|
||||
{
|
||||
o = p;
|
||||
while (IS_MSPACE(*p)) p++;
|
||||
if (o != p) { mio_mbscpy (o, p); p = o; }
|
||||
|
||||
if (lquote != MIO_MT('\0') && *p == lquote)
|
||||
{
|
||||
mio_mbscpy (p, p + 1);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (*p == MIO_MT('\0')) return -1;
|
||||
|
||||
if (escape != MIO_MT('\0') && *p == escape)
|
||||
{
|
||||
if (trset != MIO_NULL && p[1] != MIO_MT('\0'))
|
||||
{
|
||||
const mio_bch_t* ep = trset;
|
||||
while (*ep != MIO_MT('\0'))
|
||||
{
|
||||
if (p[1] == *ep++)
|
||||
{
|
||||
p[1] = *ep;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mio_mbscpy (p, p + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*p == rquote)
|
||||
{
|
||||
*p++ = MIO_MT('\0');
|
||||
cnt++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
ok = 0;
|
||||
while (IS_MSPACE(*p)) p++;
|
||||
if (*p == MIO_MT('\0')) ok = 1;
|
||||
for (d = (mio_bch_t*)delim; *d != MIO_MT('\0'); d++)
|
||||
{
|
||||
if (*p == *d)
|
||||
{
|
||||
ok = 1;
|
||||
mio_mbscpy (p, p + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ok == 0) return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
o = p; sp = ep = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (*p == MIO_MT('\0'))
|
||||
{
|
||||
if (ep)
|
||||
{
|
||||
ep[1] = MIO_MT('\0');
|
||||
p = &ep[1];
|
||||
}
|
||||
cnt++;
|
||||
break;
|
||||
}
|
||||
for (d = (mio_bch_t*)delim; *d != MIO_MT('\0'); d++)
|
||||
{
|
||||
if (*p == *d)
|
||||
{
|
||||
if (sp == MIO_NULL)
|
||||
{
|
||||
mio_mbscpy (o, p); p = o;
|
||||
*p++ = MIO_MT('\0');
|
||||
}
|
||||
else
|
||||
{
|
||||
mio_mbscpy (&ep[1], p);
|
||||
mio_mbscpy (o, sp);
|
||||
o[ep - sp + 1] = MIO_MT('\0');
|
||||
p = &o[ep - sp + 2];
|
||||
}
|
||||
cnt++;
|
||||
/* last empty field after delim */
|
||||
if (*p == MIO_MT('\0')) cnt++;
|
||||
goto exit_point;
|
||||
}
|
||||
}
|
||||
|
||||
if (!IS_MSPACE (*p))
|
||||
{
|
||||
if (sp == MIO_NULL) sp = p;
|
||||
ep = p;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
exit_point:
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
int mio_mbsspl (
|
||||
mio_bch_t* s, const mio_bch_t* delim,
|
||||
mio_bch_t lquote, mio_bch_t rquote, mio_bch_t escape)
|
||||
{
|
||||
return mio_mbsspltrn (s, delim, lquote, rquote, escape, MIO_NULL);
|
||||
}
|
||||
|
412
mio/lib/mio-utl.h
Normal file
412
mio/lib/mio-utl.h
Normal file
@ -0,0 +1,412 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
Copyright (c) 2014-2018 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_UTL_H_
|
||||
#define _MIO_UTL_H_
|
||||
|
||||
#include "mio-cmn.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The mio_equal_uchars() function determines equality of two strings
|
||||
* of the same length \a len.
|
||||
*/
|
||||
MIO_EXPORT int mio_equal_uchars (
|
||||
const mio_uch_t* str1,
|
||||
const mio_uch_t* str2,
|
||||
mio_oow_t len
|
||||
);
|
||||
|
||||
MIO_EXPORT int mio_equal_bchars (
|
||||
const mio_bch_t* str1,
|
||||
const mio_bch_t* str2,
|
||||
mio_oow_t len
|
||||
);
|
||||
|
||||
MIO_EXPORT int mio_comp_uchars (
|
||||
const mio_uch_t* str1,
|
||||
mio_oow_t len1,
|
||||
const mio_uch_t* str2,
|
||||
mio_oow_t len2
|
||||
);
|
||||
|
||||
MIO_EXPORT int mio_comp_bchars (
|
||||
const mio_bch_t* str1,
|
||||
mio_oow_t len1,
|
||||
const mio_bch_t* str2,
|
||||
mio_oow_t len2
|
||||
);
|
||||
|
||||
MIO_EXPORT int mio_comp_ucstr (
|
||||
const mio_uch_t* str1,
|
||||
const mio_uch_t* str2
|
||||
);
|
||||
|
||||
MIO_EXPORT int mio_comp_bcstr (
|
||||
const mio_bch_t* str1,
|
||||
const mio_bch_t* str2
|
||||
);
|
||||
|
||||
MIO_EXPORT int mio_comp_ucstr_bcstr (
|
||||
const mio_uch_t* str1,
|
||||
const mio_bch_t* str2
|
||||
);
|
||||
|
||||
MIO_EXPORT int mio_comp_uchars_ucstr (
|
||||
const mio_uch_t* str1,
|
||||
mio_oow_t len,
|
||||
const mio_uch_t* str2
|
||||
);
|
||||
|
||||
MIO_EXPORT int mio_comp_uchars_bcstr (
|
||||
const mio_uch_t* str1,
|
||||
mio_oow_t len,
|
||||
const mio_bch_t* str2
|
||||
);
|
||||
|
||||
MIO_EXPORT int mio_comp_bchars_bcstr (
|
||||
const mio_bch_t* str1,
|
||||
mio_oow_t len,
|
||||
const mio_bch_t* str2
|
||||
);
|
||||
|
||||
MIO_EXPORT int mio_comp_bchars_ucstr (
|
||||
const mio_bch_t* str1,
|
||||
mio_oow_t len,
|
||||
const mio_uch_t* str2
|
||||
);
|
||||
|
||||
MIO_EXPORT void mio_copy_uchars (
|
||||
mio_uch_t* dst,
|
||||
const mio_uch_t* src,
|
||||
mio_oow_t len
|
||||
);
|
||||
|
||||
MIO_EXPORT void mio_copy_bchars (
|
||||
mio_bch_t* dst,
|
||||
const mio_bch_t* src,
|
||||
mio_oow_t len
|
||||
);
|
||||
|
||||
MIO_EXPORT void mio_copy_bchars_to_uchars (
|
||||
mio_uch_t* dst,
|
||||
const mio_bch_t* src,
|
||||
mio_oow_t len
|
||||
);
|
||||
|
||||
MIO_EXPORT mio_oow_t mio_copy_ucstr (
|
||||
mio_uch_t* dst,
|
||||
mio_oow_t len,
|
||||
const mio_uch_t* src
|
||||
);
|
||||
|
||||
MIO_EXPORT mio_oow_t mio_copy_bcstr (
|
||||
mio_bch_t* dst,
|
||||
mio_oow_t len,
|
||||
const mio_bch_t* src
|
||||
);
|
||||
|
||||
MIO_EXPORT mio_uch_t* mio_find_uchar (
|
||||
const mio_uch_t* ptr,
|
||||
mio_oow_t len,
|
||||
mio_uch_t c
|
||||
);
|
||||
|
||||
MIO_EXPORT mio_bch_t* mio_find_bchar (
|
||||
const mio_bch_t* ptr,
|
||||
mio_oow_t len,
|
||||
mio_bch_t c
|
||||
);
|
||||
|
||||
MIO_EXPORT mio_uch_t* mio_rfind_uchar (
|
||||
const mio_uch_t* ptr,
|
||||
mio_oow_t len,
|
||||
mio_uch_t c
|
||||
);
|
||||
|
||||
MIO_EXPORT mio_bch_t* mio_rfind_bchar (
|
||||
const mio_bch_t* ptr,
|
||||
mio_oow_t len,
|
||||
mio_bch_t c
|
||||
);
|
||||
|
||||
MIO_EXPORT mio_uch_t* mio_find_uchar_in_ucstr (
|
||||
const mio_uch_t* ptr,
|
||||
mio_uch_t c
|
||||
);
|
||||
|
||||
MIO_EXPORT mio_bch_t* mio_find_bchar_in_bcstr (
|
||||
const mio_bch_t* ptr,
|
||||
mio_bch_t c
|
||||
);
|
||||
|
||||
MIO_EXPORT mio_oow_t mio_count_ucstr (
|
||||
const mio_uch_t* str
|
||||
);
|
||||
|
||||
MIO_EXPORT mio_oow_t mio_count_bcstr (
|
||||
const mio_bch_t* str
|
||||
);
|
||||
|
||||
#if defined(MIO_OOCH_IS_UCH)
|
||||
# define mio_equal_oochars(str1,str2,len) mio_equal_uchars(str1,str2,len)
|
||||
# define mio_comp_oochars(str1,len1,str2,len2) mio_comp_uchars(str1,len1,str2,len2)
|
||||
# define mio_comp_oocstr_bcstr(str1,str2) mio_comp_ucstr_bcstr(str1,str2)
|
||||
# define mio_comp_oochars_bcstr(str1,len1,str2) mio_comp_uchars_bcstr(str1,len1,str2)
|
||||
# define mio_comp_oochars_ucstr(str1,len1,str2) mio_comp_uchars_ucstr(str1,len1,str2)
|
||||
# define mio_comp_oochars_oocstr(str1,len1,str2) mio_comp_uchars_ucstr(str1,len1,str2)
|
||||
# define mio_comp_oocstr(str1,str2) mio_comp_ucstr(str1,str2)
|
||||
# define mio_copy_oochars(dst,src,len) mio_copy_uchars(dst,src,len)
|
||||
# define mio_copy_bchars_to_oochars(dst,src,len) mio_copy_bchars_to_uchars(dst,src,len)
|
||||
# define mio_copy_oocstr(dst,len,src) mio_copy_ucstr(dst,len,src)
|
||||
# define mio_find_oochar(ptr,len,c) mio_find_uchar(ptr,len,c)
|
||||
# define mio_rfind_oochar(ptr,len,c) mio_rfind_uchar(ptr,len,c)
|
||||
# define mio_find_oochar_in_oocstr(ptr,c) mio_find_uchar_in_ucstr(ptr,c)
|
||||
# define mio_count_oocstr(str) mio_count_ucstr(str)
|
||||
#else
|
||||
# define mio_equal_oochars(str1,str2,len) mio_equal_bchars(str1,str2,len)
|
||||
# define mio_comp_oochars(str1,len1,str2,len2) mio_comp_bchars(str1,len1,str2,len2)
|
||||
# define mio_comp_oocstr_bcstr(str1,str2) mio_comp_bcstr(str1,str2)
|
||||
# define mio_comp_oochars_bcstr(str1,len1,str2) mio_comp_bchars_bcstr(str1,len1,str2)
|
||||
# define mio_comp_oochars_ucstr(str1,len1,str2) mio_comp_bchars_ucstr(str1,len1,str2)
|
||||
# define mio_comp_oochars_oocstr(str1,len1,str2) mio_comp_bchars_bcstr(str1,len1,str2)
|
||||
# define mio_comp_oocstr(str1,str2) mio_comp_bcstr(str1,str2)
|
||||
# define mio_copy_oochars(dst,src,len) mio_copy_bchars(dst,src,len)
|
||||
# define mio_copy_bchars_to_oochars(dst,src,len) mio_copy_bchars(dst,src,len)
|
||||
# define mio_copy_oocstr(dst,len,src) mio_copy_bcstr(dst,len,src)
|
||||
# define mio_find_oochar(ptr,len,c) mio_find_bchar(ptr,len,c)
|
||||
# define mio_rfind_oochar(ptr,len,c) mio_rfind_bchar(ptr,len,c)
|
||||
# define mio_find_oochar_in_oocstr(ptr,c) mio_find_bchar_in_bcstr(ptr,c)
|
||||
# define mio_count_oocstr(str) mio_count_bcstr(str)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
MIO_EXPORT int mio_ucwidth (
|
||||
mio_uch_t uc
|
||||
);
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#if defined(MIO_OOCH_IS_UCH)
|
||||
# define mio_conv_oocs_to_bcs_with_cmgr(oocs,oocslen,bcs,bcslen,cmgr) mio_conv_ucs_to_bcs_with_cmgr(oocs,oocslen,bcs,bcslen,cmgr)
|
||||
# define mio_conv_oochars_to_bchars_with_cmgr(oocs,oocslen,bcs,bcslen,cmgr) mio_conv_uchars_to_bchars_with_cmgr(oocs,oocslen,bcs,bcslen,cmgr)
|
||||
#else
|
||||
# define mio_conv_oocs_to_ucs_with_cmgr(oocs,oocslen,ucs,ucslen,cmgr) mio_conv_bcs_to_ucs_with_cmgr(oocs,oocslen,ucs,ucslen,cmgr,0)
|
||||
# define mio_conv_oochars_to_uchars_with_cmgr(oocs,oocslen,ucs,ucslen,cmgr) mio_conv_bchars_to_uchars_with_cmgr(oocs,oocslen,ucs,ucslen,cmgr,0)
|
||||
#endif
|
||||
|
||||
|
||||
MIO_EXPORT int mio_conv_bcs_to_ucs_with_cmgr (
|
||||
const mio_bch_t* bcs,
|
||||
mio_oow_t* bcslen,
|
||||
mio_uch_t* ucs,
|
||||
mio_oow_t* ucslen,
|
||||
mio_cmgr_t* cmgr,
|
||||
int all
|
||||
);
|
||||
|
||||
MIO_EXPORT int mio_conv_bchars_to_uchars_with_cmgr (
|
||||
const mio_bch_t* bcs,
|
||||
mio_oow_t* bcslen,
|
||||
mio_uch_t* ucs,
|
||||
mio_oow_t* ucslen,
|
||||
mio_cmgr_t* cmgr,
|
||||
int all
|
||||
);
|
||||
|
||||
MIO_EXPORT int mio_conv_ucs_to_bcs_with_cmgr (
|
||||
const mio_uch_t* ucs,
|
||||
mio_oow_t* ucslen,
|
||||
mio_bch_t* bcs,
|
||||
mio_oow_t* bcslen,
|
||||
mio_cmgr_t* cmgr
|
||||
);
|
||||
|
||||
MIO_EXPORT int mio_conv_uchars_to_bchars_with_cmgr (
|
||||
const mio_uch_t* ucs,
|
||||
mio_oow_t* ucslen,
|
||||
mio_bch_t* bcs,
|
||||
mio_oow_t* bcslen,
|
||||
mio_cmgr_t* cmgr
|
||||
);
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
MIO_EXPORT mio_cmgr_t* mio_get_utf8_cmgr (
|
||||
void
|
||||
);
|
||||
|
||||
/**
|
||||
* The mio_conv_uchars_to_utf8() function converts a unicode character string \a ucs
|
||||
* to a UTF8 string and writes it into the buffer pointed to by \a bcs, but
|
||||
* not more than \a bcslen bytes including the terminating null.
|
||||
*
|
||||
* Upon return, \a bcslen is modified to the actual number of bytes written to
|
||||
* \a bcs excluding the terminating null; \a ucslen is modified to the number of
|
||||
* wide characters converted.
|
||||
*
|
||||
* You may pass #MIO_NULL for \a bcs to dry-run conversion or to get the
|
||||
* required buffer size for conversion. -2 is never returned in this case.
|
||||
*
|
||||
* \return
|
||||
* - 0 on full conversion,
|
||||
* - -1 on no or partial conversion for an illegal character encountered,
|
||||
* - -2 on no or partial conversion for a small buffer.
|
||||
*
|
||||
* \code
|
||||
* const mio_uch_t ucs[] = { 'H', 'e', 'l', 'l', 'o' };
|
||||
* mio_bch_t bcs[10];
|
||||
* mio_oow_t ucslen = 5;
|
||||
* mio_oow_t bcslen = MIO_COUNTOF(bcs);
|
||||
* n = mio_conv_uchars_to_utf8 (ucs, &ucslen, bcs, &bcslen);
|
||||
* if (n <= -1)
|
||||
* {
|
||||
* // conversion error
|
||||
* }
|
||||
* \endcode
|
||||
*/
|
||||
MIO_EXPORT int mio_conv_uchars_to_utf8 (
|
||||
const mio_uch_t* ucs,
|
||||
mio_oow_t* ucslen,
|
||||
mio_bch_t* bcs,
|
||||
mio_oow_t* bcslen
|
||||
);
|
||||
|
||||
/**
|
||||
* The mio_conv_utf8_to_uchars() function converts a UTF8 string to a uncide string.
|
||||
*
|
||||
* It never returns -2 if \a ucs is #MIO_NULL.
|
||||
*
|
||||
* \code
|
||||
* const mio_bch_t* bcs = "test string";
|
||||
* mio_uch_t ucs[100];
|
||||
* mio_oow_t ucslen = MIO_COUNTOF(buf), n;
|
||||
* mio_oow_t bcslen = 11;
|
||||
* int n;
|
||||
* n = mio_conv_utf8_to_uchars (bcs, &bcslen, ucs, &ucslen);
|
||||
* if (n <= -1) { invalid/incomplenete sequence or buffer to small }
|
||||
* \endcode
|
||||
*
|
||||
* The resulting \a ucslen can still be greater than 0 even if the return
|
||||
* value is negative. The value indiates the number of characters converted
|
||||
* before the error has occurred.
|
||||
*
|
||||
* \return 0 on success.
|
||||
* -1 if \a bcs contains an illegal character.
|
||||
* -2 if the wide-character string buffer is too small.
|
||||
* -3 if \a bcs is not a complete sequence.
|
||||
*/
|
||||
MIO_EXPORT int mio_conv_utf8_to_uchars (
|
||||
const mio_bch_t* bcs,
|
||||
mio_oow_t* bcslen,
|
||||
mio_uch_t* ucs,
|
||||
mio_oow_t* ucslen
|
||||
);
|
||||
|
||||
|
||||
MIO_EXPORT int mio_conv_ucstr_to_utf8 (
|
||||
const mio_uch_t* ucs,
|
||||
mio_oow_t* ucslen,
|
||||
mio_bch_t* bcs,
|
||||
mio_oow_t* bcslen
|
||||
);
|
||||
|
||||
MIO_EXPORT int mio_conv_utf8_to_ucstr (
|
||||
const mio_bch_t* bcs,
|
||||
mio_oow_t* bcslen,
|
||||
mio_uch_t* ucs,
|
||||
mio_oow_t* ucslen
|
||||
);
|
||||
|
||||
|
||||
MIO_EXPORT mio_oow_t mio_uc_to_utf8 (
|
||||
mio_uch_t uc,
|
||||
mio_bch_t* utf8,
|
||||
mio_oow_t size
|
||||
);
|
||||
|
||||
MIO_EXPORT mio_oow_t mio_utf8_to_uc (
|
||||
const mio_bch_t* utf8,
|
||||
mio_oow_t size,
|
||||
mio_uch_t* uc
|
||||
);
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#if defined(MIO_HAVE_UINT16_T)
|
||||
MIO_EXPORT mio_uint16_t mio_ntoh16 (
|
||||
mio_uint16_t x
|
||||
);
|
||||
|
||||
MIO_EXPORT mio_uint16_t mio_hton16 (
|
||||
mio_uint16_t x
|
||||
);
|
||||
#endif
|
||||
|
||||
#if defined(MIO_HAVE_UINT32_T)
|
||||
MIO_EXPORT mio_uint32_t mio_ntoh32 (
|
||||
mio_uint32_t x
|
||||
);
|
||||
|
||||
MIO_EXPORT mio_uint32_t mio_hton32 (
|
||||
mio_uint32_t x
|
||||
);
|
||||
#endif
|
||||
|
||||
#if defined(MIO_HAVE_UINT64_T)
|
||||
MIO_EXPORT mio_uint64_t mio_ntoh64 (
|
||||
mio_uint64_t x
|
||||
);
|
||||
|
||||
MIO_EXPORT mio_uint64_t mio_hton64 (
|
||||
mio_uint64_t x
|
||||
);
|
||||
#endif
|
||||
|
||||
#if defined(MIO_HAVE_UINT128_T)
|
||||
MIO_EXPORT mio_uint128_t mio_ntoh128 (
|
||||
mio_uint128_t x
|
||||
);
|
||||
|
||||
MIO_EXPORT mio_uint128_t mio_hton128 (
|
||||
mio_uint128_t x
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -99,7 +99,7 @@ static int mux_open (mio_t* mio)
|
||||
mux = MIO_MMGR_ALLOC (mio->mmgr, MIO_SIZEOF(*mux));
|
||||
if (!mux)
|
||||
{
|
||||
mio->errnum = MIO_ENOMEM;
|
||||
mio->errnum = MIO_ESYSMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -143,7 +143,7 @@ static int mux_control (mio_dev_t* dev, int cmd, mio_syshnd_t hnd, int dev_capa)
|
||||
tmp = MIO_MMGR_REALLOC(mio->mmgr, mux->map.ptr, new_capa * MIO_SIZEOF(*tmp));
|
||||
if (!tmp)
|
||||
{
|
||||
mio->errnum = MIO_ENOMEM;
|
||||
mio->errnum = MIO_ESYSMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -187,7 +187,7 @@ static int mux_control (mio_dev_t* dev, int cmd, mio_syshnd_t hnd, int dev_capa)
|
||||
tmp1 = MIO_MMGR_REALLOC(mio->mmgr, mux->pd.pfd, new_capa * MIO_SIZEOF(*tmp1));
|
||||
if (!tmp1)
|
||||
{
|
||||
mio->errnum = MIO_ENOMEM;
|
||||
mio->errnum = MIO_ESYSMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -195,7 +195,7 @@ static int mux_control (mio_dev_t* dev, int cmd, mio_syshnd_t hnd, int dev_capa)
|
||||
if (!tmp2)
|
||||
{
|
||||
MIO_MMGR_FREE (mio->mmgr, tmp1);
|
||||
mio->errnum = MIO_ENOMEM;
|
||||
mio->errnum = MIO_ESYSMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -276,7 +276,7 @@ static int mux_open (mio_t* mio)
|
||||
mux = MIO_MMGR_ALLOC (mio->mmgr, MIO_SIZEOF(*mux));
|
||||
if (!mux)
|
||||
{
|
||||
mio->errnum = MIO_ENOMEM;
|
||||
mio->errnum = MIO_ESYSMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -352,7 +352,7 @@ mio_t* mio_open (mio_mmgr_t* mmgr, mio_oow_t xtnsize, mio_oow_t tmrcapa, mio_err
|
||||
}
|
||||
else
|
||||
{
|
||||
if (errnum) *errnum = MIO_ENOMEM;
|
||||
if (errnum) *errnum = MIO_ESYSMEM;
|
||||
}
|
||||
|
||||
return mio;
|
||||
@ -378,7 +378,7 @@ int mio_init (mio_t* mio, mio_mmgr_t* mmgr, mio_oow_t tmrcapa)
|
||||
mio->tmr.jobs = MIO_MMGR_ALLOC (mio->mmgr, tmrcapa * MIO_SIZEOF(mio_tmrjob_t));
|
||||
if (!mio->tmr.jobs)
|
||||
{
|
||||
mio->errnum = MIO_ENOMEM;
|
||||
mio->errnum = MIO_ESYSMEM;
|
||||
mux_close (mio);
|
||||
return -1;
|
||||
}
|
||||
@ -938,7 +938,7 @@ mio_dev_t* mio_makedev (mio_t* mio, mio_oow_t dev_size, mio_dev_mth_t* dev_mth,
|
||||
dev = MIO_MMGR_ALLOC(mio->mmgr, dev_size);
|
||||
if (!dev)
|
||||
{
|
||||
mio->errnum = MIO_ENOMEM;
|
||||
mio->errnum = MIO_ESYSMEM;
|
||||
return MIO_NULL;
|
||||
}
|
||||
|
||||
@ -1202,7 +1202,7 @@ void mio_dev_halt (mio_dev_t* dev)
|
||||
int mio_dev_ioctl (mio_dev_t* dev, int cmd, void* arg)
|
||||
{
|
||||
if (dev->dev_mth->ioctl) return dev->dev_mth->ioctl (dev, cmd, arg);
|
||||
dev->mio->errnum = MIO_ENOSUP; /* TODO: different error code ? */
|
||||
dev->mio->errnum = MIO_ENOIMPL; /* TODO: different error code ? */
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1502,7 +1502,7 @@ enqueue_data:
|
||||
q = (mio_wq_t*)MIO_MMGR_ALLOC(dev->mio->mmgr, MIO_SIZEOF(*q) + (dstaddr? dstaddr->len: 0) + urem);
|
||||
if (!q)
|
||||
{
|
||||
dev->mio->errnum = MIO_ENOMEM;
|
||||
dev->mio->errnum = MIO_ESYSMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1580,7 +1580,7 @@ enqueue_completed_write:
|
||||
cwq = (mio_cwq_t*)MIO_MMGR_ALLOC(dev->mio->mmgr, MIO_SIZEOF(*cwq) + cwq_extra_aligned);
|
||||
if (!cwq)
|
||||
{
|
||||
dev->mio->errnum = MIO_ENOMEM;
|
||||
dev->mio->errnum = MIO_ESYSMEM;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -1640,7 +1640,7 @@ mio_errnum_t mio_syserrtoerrnum (int no)
|
||||
switch (no)
|
||||
{
|
||||
case ENOMEM:
|
||||
return MIO_ENOMEM;
|
||||
return MIO_ESYSMEM;
|
||||
|
||||
case EINVAL:
|
||||
return MIO_EINVAL;
|
||||
@ -1690,3 +1690,37 @@ mio_errnum_t mio_syserrtoerrnum (int no)
|
||||
return MIO_ESYSERR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void* mio_allocmem (mio_t* mio, mio_oow_t size)
|
||||
{
|
||||
void* ptr;
|
||||
|
||||
ptr = MIO_MMGR_ALLOC (mio->mmgr, size);
|
||||
if (!ptr) mio_seterrnum (mio, MIO_ESYSMEM);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void* mio_callocmem (mio_t* mio, mio_oow_t size)
|
||||
{
|
||||
void* ptr;
|
||||
|
||||
ptr = MIO_MMGR_ALLOC (mio->mmgr, size);
|
||||
if (!ptr) mio_seterrnum (mio, MIO_ESYSMEM);
|
||||
else MIO_MEMSET (ptr, 0, size);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void* mio_reallocmem (mio_t* mio, void* ptr, mio_oow_t size)
|
||||
{
|
||||
ptr = MIO_MMGR_REALLOC (mio->mmgr, ptr, size);
|
||||
if (!ptr) mio_seterrnum (mio, MIO_ESYSMEM);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void mio_freemem (mio_t* mio, void* ptr)
|
||||
{
|
||||
MIO_MMGR_FREE (mio->mmgr, ptr);
|
||||
}
|
||||
|
381
mio/lib/mio.h
381
mio/lib/mio.h
@ -80,34 +80,60 @@ typedef struct mio_wq_t mio_wq_t;
|
||||
typedef struct mio_cwq_t mio_cwq_t;
|
||||
typedef mio_intptr_t mio_iolen_t; /* NOTE: this is a signed type */
|
||||
|
||||
typedef unsigned int mio_bitmask_t;
|
||||
|
||||
enum mio_errnum_t
|
||||
{
|
||||
MIO_ENOERR,
|
||||
MIO_ENOIMPL,
|
||||
MIO_ESYSERR,
|
||||
MIO_EINTERN,
|
||||
MIO_ENOERR, /**< no error */
|
||||
MIO_EGENERIC, /**< generic error */
|
||||
|
||||
MIO_ENOIMPL, /**< not implemented */
|
||||
MIO_ESYSERR, /**< system error */
|
||||
MIO_EINTERN, /**< internal error */
|
||||
MIO_ESYSMEM, /**< insufficient system memory */
|
||||
MIO_EOOMEM, /**< insufficient object memory */
|
||||
MIO_ETYPE, /**< invalid class/type */
|
||||
|
||||
MIO_EINVAL, /**< invalid parameter or data */
|
||||
MIO_ENOENT, /**< data not found */
|
||||
MIO_EEXIST, /**< existing/duplicate data */
|
||||
MIO_EBUSY,
|
||||
MIO_EACCES,
|
||||
MIO_EPERM, /**< operation not permitted */
|
||||
MIO_ENOTDIR,
|
||||
MIO_EINTR,
|
||||
MIO_EPIPE,
|
||||
MIO_EAGAIN,
|
||||
MIO_EBADHND,
|
||||
|
||||
MIO_ENOMEM,
|
||||
MIO_EINVAL,
|
||||
MIO_EEXIST,
|
||||
MIO_ENOENT,
|
||||
MIO_ENOSUP, /* not supported */
|
||||
MIO_EMFILE, /* too many open files */
|
||||
MIO_ENFILE,
|
||||
MIO_EAGAIN,
|
||||
|
||||
MIO_EIOERR, /**< I/O error */
|
||||
MIO_EECERR, /**< encoding conversion error */
|
||||
MIO_EECMORE, /**< insufficient data for encoding conversion */
|
||||
MIO_EBUFFULL, /**< buffer full */
|
||||
|
||||
MIO_ECONRF, /* connection refused */
|
||||
MIO_ECONRS, /* connection reset */
|
||||
MIO_ENOCAPA, /* no capability */
|
||||
MIO_ETMOUT, /* timed out */
|
||||
MIO_EPERM, /* operation not permitted */
|
||||
|
||||
MIO_EDEVMAKE,
|
||||
MIO_EDEVERR,
|
||||
MIO_EDEVHUP
|
||||
};
|
||||
|
||||
typedef enum mio_errnum_t mio_errnum_t;
|
||||
|
||||
#define MIO_ERRMSG_CAPA (2048)
|
||||
|
||||
struct mio_errinf_t
|
||||
{
|
||||
mio_errnum_t num;
|
||||
mio_ooch_t msg[MIO_ERRMSG_CAPA];
|
||||
};
|
||||
typedef struct mio_errinf_t mio_errinf_t;
|
||||
|
||||
enum mio_stopreq_t
|
||||
{
|
||||
MIO_STOPREQ_NONE = 0,
|
||||
@ -364,6 +390,71 @@ enum mio_dev_event_t
|
||||
typedef enum mio_dev_event_t mio_dev_event_t;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#define MIO_CWQFL_SIZE 16
|
||||
#define MIO_CWQFL_ALIGN 16
|
||||
|
||||
typedef struct mio_mux_t mio_mux_t;
|
||||
|
||||
struct mio_t
|
||||
{
|
||||
mio_mmgr_t* mmgr;
|
||||
mio_cmgr_t* cmgr;
|
||||
mio_errnum_t errnum;
|
||||
struct
|
||||
{
|
||||
union
|
||||
{
|
||||
mio_ooch_t ooch[MIO_ERRMSG_CAPA];
|
||||
mio_bch_t bch[MIO_ERRMSG_CAPA];
|
||||
mio_uch_t uch[MIO_ERRMSG_CAPA];
|
||||
} tmpbuf;
|
||||
mio_ooch_t buf[MIO_ERRMSG_CAPA];
|
||||
mio_oow_t len;
|
||||
} errmsg;
|
||||
int shuterr;
|
||||
|
||||
mio_stopreq_t stopreq; /* stop request to abort mio_loop() */
|
||||
|
||||
struct
|
||||
{
|
||||
mio_dev_t* head;
|
||||
mio_dev_t* tail;
|
||||
} actdev; /* active devices */
|
||||
|
||||
struct
|
||||
{
|
||||
mio_dev_t* head;
|
||||
mio_dev_t* tail;
|
||||
} hltdev; /* halted devices */
|
||||
|
||||
struct
|
||||
{
|
||||
mio_dev_t* head;
|
||||
mio_dev_t* tail;
|
||||
} zmbdev; /* zombie devices */
|
||||
|
||||
mio_uint8_t bigbuf[65535]; /* TODO: make this dynamic depending on devices added. device may indicate a buffer size required??? */
|
||||
|
||||
unsigned int renew_watch: 1;
|
||||
unsigned int in_exec: 1;
|
||||
|
||||
struct
|
||||
{
|
||||
mio_oow_t capa;
|
||||
mio_oow_t size;
|
||||
mio_tmrjob_t* jobs;
|
||||
} tmr;
|
||||
|
||||
mio_cwq_t cwq;
|
||||
mio_cwq_t* cwqfl[MIO_CWQFL_SIZE]; /* list of free cwq objects */
|
||||
|
||||
/* platform specific fields below */
|
||||
mio_mux_t* mux;
|
||||
};
|
||||
|
||||
/* ========================================================================= */
|
||||
|
||||
#ifdef __cplusplus
|
||||
@ -391,6 +482,84 @@ MIO_EXPORT void mio_fini (
|
||||
mio_t* mio
|
||||
);
|
||||
|
||||
|
||||
#if defined(MIO_HAVE_INLINE)
|
||||
static MIO_INLINE mio_mmgr_t* mio_getmmgr (mio_t* mio) { return mio->mmgr; }
|
||||
static MIO_INLINE void* mio_getxtn (mio_t* mio) { return (void*)(mio + 1); }
|
||||
|
||||
static MIO_INLINE mio_cmgr_t* mio_getcmgr (mio_t* mio) { return mio->cmgr; }
|
||||
static MIO_INLINE void mio_setcmgr (mio_t* mio, mio_cmgr_t* cmgr) { mio->cmgr = cmgr; }
|
||||
|
||||
static MIO_INLINE mio_errnum_t mio_geterrnum (mio_t* mio) { return mio->errnum; }
|
||||
#else
|
||||
# define mio_getmmgr(mio) ((mio)->mmgr)
|
||||
# define mio_getxtn(mio) ((void*)((mio) + 1))
|
||||
|
||||
# define mio_getcmgr(mio) ((mio)->cmgr)
|
||||
# define mio_setcmgr(mio,mgr) ((mio)->cmgr = (mgr))
|
||||
|
||||
# define mio_geterrnum(mio) ((mio)->errnum)
|
||||
#endif
|
||||
|
||||
MIO_EXPORT void mio_seterrnum (
|
||||
mio_t* mio,
|
||||
mio_errnum_t errnum
|
||||
);
|
||||
|
||||
MIO_EXPORT void mio_seterrwithsyserr (
|
||||
mio_t* mio,
|
||||
int syserr_type,
|
||||
int syserr_code
|
||||
);
|
||||
|
||||
MIO_EXPORT void mio_seterrbfmt (
|
||||
mio_t* mio,
|
||||
mio_errnum_t errnum,
|
||||
const mio_bch_t* fmt,
|
||||
...
|
||||
);
|
||||
|
||||
MIO_EXPORT void mio_seterrufmt (
|
||||
mio_t* mio,
|
||||
mio_errnum_t errnum,
|
||||
const mio_uch_t* fmt,
|
||||
...
|
||||
);
|
||||
|
||||
MIO_EXPORT void mio_seterrbfmtwithsyserr (
|
||||
mio_t* mio,
|
||||
int syserr_type,
|
||||
int syserr_code,
|
||||
const mio_bch_t* fmt,
|
||||
...
|
||||
);
|
||||
|
||||
MIO_EXPORT void mio_seterrufmtwithsyserr (
|
||||
mio_t* mio,
|
||||
int syserr_type,
|
||||
int syserr_code,
|
||||
const mio_uch_t* fmt,
|
||||
...
|
||||
);
|
||||
|
||||
MIO_EXPORT const mio_ooch_t* mio_geterrstr (
|
||||
mio_t* mio
|
||||
);
|
||||
|
||||
MIO_EXPORT const mio_ooch_t* mio_geterrmsg (
|
||||
mio_t* mio
|
||||
);
|
||||
|
||||
MIO_EXPORT void mio_geterrinf (
|
||||
mio_t* mio,
|
||||
mio_errinf_t* info
|
||||
);
|
||||
|
||||
MIO_EXPORT const mio_ooch_t* mio_backuperrmsg (
|
||||
mio_t* mio
|
||||
);
|
||||
|
||||
|
||||
MIO_EXPORT int mio_exec (
|
||||
mio_t* mio
|
||||
);
|
||||
@ -549,50 +718,186 @@ MIO_EXPORT int mio_gettmrjobdeadline (
|
||||
mio_ntime_t* deadline
|
||||
);
|
||||
|
||||
/* ========================================================================= */
|
||||
|
||||
|
||||
#if defined(MIO_HAVE_UINT16_T)
|
||||
MIO_EXPORT mio_uint16_t mio_ntoh16 (
|
||||
mio_uint16_t x
|
||||
/* =========================================================================
|
||||
* SYSTEM MEMORY MANAGEMENT FUCNTIONS VIA MMGR
|
||||
* ========================================================================= */
|
||||
MIO_EXPORT void* mio_allocmem (
|
||||
mio_t* mio,
|
||||
mio_oow_t size
|
||||
);
|
||||
|
||||
MIO_EXPORT mio_uint16_t mio_hton16 (
|
||||
mio_uint16_t x
|
||||
MIO_EXPORT void* mio_callocmem (
|
||||
mio_t* mio,
|
||||
mio_oow_t size
|
||||
);
|
||||
|
||||
MIO_EXPORT void* mio_reallocmem (
|
||||
mio_t* mio,
|
||||
void* ptr,
|
||||
mio_oow_t size
|
||||
);
|
||||
|
||||
MIO_EXPORT void mio_freemem (
|
||||
mio_t* mio,
|
||||
void* ptr
|
||||
);
|
||||
|
||||
/* =========================================================================
|
||||
* STRING ENCODING CONVERSION
|
||||
* ========================================================================= */
|
||||
|
||||
#if defined(MIO_OOCH_IS_UCH)
|
||||
# define mio_convootobchars(mio,oocs,oocslen,bcs,bcslen) mio_convutobchars(mio,oocs,oocslen,bcs,bcslen)
|
||||
# define mio_convbtooochars(mio,bcs,bcslen,oocs,oocslen) mio_convbtouchars(mio,bcs,bcslen,oocs,oocslen)
|
||||
# define mio_convootobcstr(mio,oocs,oocslen,bcs,bcslen) mio_convutobcstr(mio,oocs,oocslen,bcs,bcslen)
|
||||
# define mio_convbtooocstr(mio,bcs,bcslen,oocs,oocslen) mio_convbtoucstr(mio,bcs,bcslen,oocs,oocslen)
|
||||
#else
|
||||
# define mio_convootouchars(mio,oocs,oocslen,bcs,bcslen) mio_convbtouchars(mio,oocs,oocslen,bcs,bcslen)
|
||||
# define mio_convutooochars(mio,bcs,bcslen,oocs,oocslen) mio_convutobchars(mio,bcs,bcslen,oocs,oocslen)
|
||||
# define mio_convootoucstr(mio,oocs,oocslen,bcs,bcslen) mio_convbtoucstr(mio,oocs,oocslen,bcs,bcslen)
|
||||
# define mio_convutooocstr(mio,bcs,bcslen,oocs,oocslen) mio_convutobcstr(mio,bcs,bcslen,oocs,oocslen)
|
||||
#endif
|
||||
|
||||
#if defined(MIO_HAVE_UINT32_T)
|
||||
MIO_EXPORT mio_uint32_t mio_ntoh32 (
|
||||
mio_uint32_t x
|
||||
MIO_EXPORT int mio_convbtouchars (
|
||||
mio_t* mio,
|
||||
const mio_bch_t* bcs,
|
||||
mio_oow_t* bcslen,
|
||||
mio_uch_t* ucs,
|
||||
mio_oow_t* ucslen
|
||||
);
|
||||
|
||||
MIO_EXPORT mio_uint32_t mio_hton32 (
|
||||
mio_uint32_t x
|
||||
MIO_EXPORT int mio_convutobchars (
|
||||
mio_t* mio,
|
||||
const mio_uch_t* ucs,
|
||||
mio_oow_t* ucslen,
|
||||
mio_bch_t* bcs,
|
||||
mio_oow_t* bcslen
|
||||
);
|
||||
|
||||
/**
|
||||
* The mio_convbtoucstr() function converts a null-terminated byte string
|
||||
* to a wide string.
|
||||
*/
|
||||
MIO_EXPORT int mio_convbtoucstr (
|
||||
mio_t* mio,
|
||||
const mio_bch_t* bcs,
|
||||
mio_oow_t* bcslen,
|
||||
mio_uch_t* ucs,
|
||||
mio_oow_t* ucslen
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* The mio_convutobcstr() function converts a null-terminated wide string
|
||||
* to a byte string.
|
||||
*/
|
||||
MIO_EXPORT int mio_convutobcstr (
|
||||
mio_t* mio,
|
||||
const mio_uch_t* ucs,
|
||||
mio_oow_t* ucslen,
|
||||
mio_bch_t* bcs,
|
||||
mio_oow_t* bcslen
|
||||
);
|
||||
|
||||
|
||||
#if defined(MIO_OOCH_IS_UCH)
|
||||
# define mio_dupootobcharswithheadroom(mio,hrb,oocs,oocslen,bcslen) mio_duputobcharswithheadroom(mio,hrb,oocs,oocslen,bcslen)
|
||||
# define mio_dupbtooocharswithheadroom(mio,hrb,bcs,bcslen,oocslen) mio_dupbtoucharswithheadroom(mio,hrb,bcs,bcslen,oocslen)
|
||||
# define mio_dupootobchars(mio,oocs,oocslen,bcslen) mio_duputobchars(mio,oocs,oocslen,bcslen)
|
||||
# define mio_dupbtooochars(mio,bcs,bcslen,oocslen) mio_dupbtouchars(mio,bcs,bcslen,oocslen)
|
||||
|
||||
# define mio_dupootobcstrwithheadroom(mio,hrb,oocs,bcslen) mio_duputobcstrwithheadroom(mio,hrb,oocs,bcslen)
|
||||
# define mio_dupbtooocstrwithheadroom(mio,hrb,bcs,oocslen) mio_dupbtoucstrwithheadroom(mio,hrb,bcs,oocslen)
|
||||
# define mio_dupootobcstr(mio,oocs,bcslen) mio_duputobcstr(mio,oocs,bcslen)
|
||||
# define mio_dupbtooocstr(mio,bcs,oocslen) mio_dupbtoucstr(mio,bcs,oocslen)
|
||||
#else
|
||||
# define mio_dupootoucharswithheadroom(mio,hrb,oocs,oocslen,ucslen) mio_dupbtoucharswithheadroom(mio,hrb,oocs,oocslen,ucslen)
|
||||
# define mio_duputooocharswithheadroom(mio,hrb,ucs,ucslen,oocslen) mio_duputobcharswithheadroom(mio,hrb,ucs,ucslen,oocslen)
|
||||
# define mio_dupootouchars(mio,oocs,oocslen,ucslen) mio_dupbtouchars(mio,oocs,oocslen,ucslen)
|
||||
# define mio_duputooochars(mio,ucs,ucslen,oocslen) mio_duputobchars(mio,ucs,ucslen,oocslen)
|
||||
|
||||
# define mio_dupootoucstrwithheadroom(mio,hrb,oocs,ucslen) mio_dupbtoucstrwithheadroom(mio,hrb,oocs,ucslen)
|
||||
# define mio_duputooocstrwithheadroom(mio,hrb,ucs,oocslen) mio_duputobcstrwithheadroom(mio,hrb,ucs,oocslen)
|
||||
# define mio_dupootoucstr(mio,oocs,ucslen) mio_dupbtoucstr(mio,oocs,ucslen)
|
||||
# define mio_duputooocstr(mio,ucs,oocslen) mio_duputobcstr(mio,ucs,oocslen)
|
||||
#endif
|
||||
|
||||
#if defined(MIO_HAVE_UINT64_T)
|
||||
MIO_EXPORT mio_uint64_t mio_ntoh64 (
|
||||
mio_uint64_t x
|
||||
|
||||
MIO_EXPORT mio_uch_t* mio_dupbtoucharswithheadroom (
|
||||
mio_t* mio,
|
||||
mio_oow_t headroom_bytes,
|
||||
const mio_bch_t* bcs,
|
||||
mio_oow_t bcslen,
|
||||
mio_oow_t* ucslen
|
||||
);
|
||||
|
||||
MIO_EXPORT mio_uint64_t mio_hton64 (
|
||||
mio_uint64_t x
|
||||
MIO_EXPORT mio_bch_t* mio_duputobcharswithheadroom (
|
||||
mio_t* mio,
|
||||
mio_oow_t headroom_bytes,
|
||||
const mio_uch_t* ucs,
|
||||
mio_oow_t ucslen,
|
||||
mio_oow_t* bcslen
|
||||
);
|
||||
|
||||
MIO_EXPORT mio_uch_t* mio_dupbtouchars (
|
||||
mio_t* mio,
|
||||
const mio_bch_t* bcs,
|
||||
mio_oow_t bcslen,
|
||||
mio_oow_t* ucslen
|
||||
);
|
||||
|
||||
MIO_EXPORT mio_bch_t* mio_duputobchars (
|
||||
mio_t* mio,
|
||||
const mio_uch_t* ucs,
|
||||
mio_oow_t ucslen,
|
||||
mio_oow_t* bcslen
|
||||
);
|
||||
|
||||
|
||||
MIO_EXPORT mio_uch_t* mio_dupbtoucstrwithheadroom (
|
||||
mio_t* mio,
|
||||
mio_oow_t headroom_bytes,
|
||||
const mio_bch_t* bcs,
|
||||
mio_oow_t* ucslen
|
||||
);
|
||||
|
||||
MIO_EXPORT mio_bch_t* mio_duputobcstrwithheadroom (
|
||||
mio_t* mio,
|
||||
mio_oow_t headroom_bytes,
|
||||
const mio_uch_t* ucs,
|
||||
mio_oow_t* bcslen
|
||||
);
|
||||
|
||||
MIO_EXPORT mio_uch_t* mio_dupbtoucstr (
|
||||
mio_t* mio,
|
||||
const mio_bch_t* bcs,
|
||||
mio_oow_t* ucslen /* optional: length of returned string */
|
||||
);
|
||||
|
||||
MIO_EXPORT mio_bch_t* mio_duputobcstr (
|
||||
mio_t* mio,
|
||||
const mio_uch_t* ucs,
|
||||
mio_oow_t* bcslen /* optional: length of returned string */
|
||||
);
|
||||
|
||||
|
||||
#if defined(MIO_OOCH_IS_UCH)
|
||||
# define mio_dupoochars(mio,oocs,oocslen) mio_dupuchars(mio,oocs,oocslen)
|
||||
#else
|
||||
# define mio_dupoochars(mio,oocs,oocslen) mio_dupbchars(mio,oocs,oocslen)
|
||||
#endif
|
||||
|
||||
#if defined(MIO_HAVE_UINT128_T)
|
||||
MIO_EXPORT mio_uint128_t mio_ntoh128 (
|
||||
mio_uint128_t x
|
||||
MIO_EXPORT mio_uch_t* mio_dupuchars (
|
||||
mio_t* mio,
|
||||
const mio_uch_t* ucs,
|
||||
mio_oow_t ucslen
|
||||
);
|
||||
|
||||
MIO_EXPORT mio_uint128_t mio_hton128 (
|
||||
mio_uint128_t x
|
||||
MIO_EXPORT mio_bch_t* mio_dupbchars (
|
||||
mio_t* mio,
|
||||
const mio_bch_t* bcs,
|
||||
mio_oow_t bcslen
|
||||
);
|
||||
#endif
|
||||
|
||||
/* ========================================================================= */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -1,3 +1,53 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
Copyright (c) 2015-2016 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 WAfRRANTIES
|
||||
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-prv.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#if defined(HAVE_NETINET_IN_H)
|
||||
# include <netinet/in.h>
|
||||
#endif
|
||||
#if defined(HAVE_SYS_UN_H)
|
||||
# include <sys/un.h>
|
||||
#endif
|
||||
#if defined(HAVE_NETPACKET_PACKET_H)
|
||||
# include <netpacket/packet.h>
|
||||
#endif
|
||||
#if defined(HAVE_NET_IF_DL_H)
|
||||
# include <net/if_dl.h>
|
||||
#endif
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
union sockaddr_t
|
||||
{
|
||||
struct sockaddr sa;
|
||||
@ -16,385 +66,31 @@ union sockaddr_t
|
||||
};
|
||||
typedef union sockaddr_t sockaddr_t;
|
||||
|
||||
|
||||
static int str_to_ipv4 (const mio_ooch_t* str, mio_oow_t len, struct in_addr* inaddr)
|
||||
{
|
||||
const mio_ooch_t* end;
|
||||
int dots = 0, digits = 0;
|
||||
mio_uint32_t acc = 0, addr = 0;
|
||||
mio_ooch_t c;
|
||||
|
||||
end = str + len;
|
||||
|
||||
do
|
||||
{
|
||||
if (str >= end)
|
||||
{
|
||||
if (dots < 3 || digits == 0) return -1;
|
||||
addr = (addr << 8) | acc;
|
||||
break;
|
||||
}
|
||||
|
||||
c = *str++;
|
||||
|
||||
if (c >= '0' && c <= '9')
|
||||
{
|
||||
if (digits > 0 && acc == 0) return -1;
|
||||
acc = acc * 10 + (c - '0');
|
||||
if (acc > 255) return -1;
|
||||
digits++;
|
||||
}
|
||||
else if (c == '.')
|
||||
{
|
||||
if (dots >= 3 || digits == 0) return -1;
|
||||
addr = (addr << 8) | acc;
|
||||
dots++; acc = 0; digits = 0;
|
||||
}
|
||||
else return -1;
|
||||
}
|
||||
while (1);
|
||||
|
||||
inaddr->s_addr = mio_hton32(addr);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
#if (MIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0)
|
||||
static int str_to_ipv6 (const mio_ooch_t* src, mio_oow_t len, struct in6_addr* inaddr)
|
||||
{
|
||||
mio_uint8_t* tp, * endp, * colonp;
|
||||
const mio_ooch_t* curtok;
|
||||
mio_ooch_t ch;
|
||||
int saw_xdigit;
|
||||
unsigned int val;
|
||||
const mio_ooch_t* src_end;
|
||||
|
||||
src_end = src + len;
|
||||
|
||||
MIO_MEMSET (inaddr, 0, MIO_SIZEOF(*inaddr));
|
||||
tp = &inaddr->s6_addr[0];
|
||||
endp = &inaddr->s6_addr[MIO_COUNTOF(inaddr->s6_addr)];
|
||||
colonp = MIO_NULL;
|
||||
|
||||
/* Leading :: requires some special handling. */
|
||||
if (src < src_end && *src == ':')
|
||||
{
|
||||
src++;
|
||||
if (src >= src_end || *src != ':') return -1;
|
||||
}
|
||||
|
||||
curtok = src;
|
||||
saw_xdigit = 0;
|
||||
val = 0;
|
||||
|
||||
while (src < src_end)
|
||||
{
|
||||
int v1;
|
||||
|
||||
ch = *src++;
|
||||
|
||||
if (ch >= '0' && ch <= '9')
|
||||
v1 = ch - '0';
|
||||
else if (ch >= 'A' && ch <= 'F')
|
||||
v1 = ch - 'A' + 10;
|
||||
else if (ch >= 'a' && ch <= 'f')
|
||||
v1 = ch - 'a' + 10;
|
||||
else v1 = -1;
|
||||
if (v1 >= 0)
|
||||
{
|
||||
val <<= 4;
|
||||
val |= v1;
|
||||
if (val > 0xffff) return -1;
|
||||
saw_xdigit = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ch == ':')
|
||||
{
|
||||
curtok = src;
|
||||
if (!saw_xdigit)
|
||||
{
|
||||
if (colonp) return -1;
|
||||
colonp = tp;
|
||||
continue;
|
||||
}
|
||||
else if (src >= src_end)
|
||||
{
|
||||
/* a colon can't be the last character */
|
||||
return -1;
|
||||
}
|
||||
|
||||
*tp++ = (mio_uint8_t)(val >> 8) & 0xff;
|
||||
*tp++ = (mio_uint8_t)val & 0xff;
|
||||
saw_xdigit = 0;
|
||||
val = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ch == '.' && ((tp + MIO_SIZEOF(struct in_addr)) <= endp) &&
|
||||
str_to_ipv4(curtok, src_end - curtok, (struct in_addr*)tp) == 0)
|
||||
{
|
||||
tp += MIO_SIZEOF(struct in_addr*);
|
||||
saw_xdigit = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (saw_xdigit)
|
||||
{
|
||||
if (tp + MIO_SIZEOF(mio_uint16_t) > endp) return -1;
|
||||
*tp++ = (mio_uint8_t)(val >> 8) & 0xff;
|
||||
*tp++ = (mio_uint8_t)val & 0xff;
|
||||
}
|
||||
if (colonp != MIO_NULL)
|
||||
{
|
||||
/*
|
||||
* Since some memmove()'s erroneously fail to handle
|
||||
* overlapping regions, we'll do the shift by hand.
|
||||
*/
|
||||
mio_oow_t n = tp - colonp;
|
||||
mio_oow_t i;
|
||||
|
||||
for (i = 1; i <= n; i++)
|
||||
{
|
||||
endp[-i] = colonp[n - i];
|
||||
colonp[n - i] = 0;
|
||||
}
|
||||
tp = endp;
|
||||
}
|
||||
|
||||
if (tp != endp) return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#undef char_t
|
||||
#undef cstr_t
|
||||
#undef str_to_sockaddr
|
||||
#undef str_to_ipv4
|
||||
#undef str_to_ipv6
|
||||
#define CHAR_T_IS_BCH
|
||||
#undef CHAR_T_IS_UCH
|
||||
#define char_t mio_bch_t
|
||||
#define cstr_t mio_bcs_t
|
||||
#define str_to_sockaddr bcstr_to_sockaddr
|
||||
#define str_to_ipv4 bcstr_to_ipv4
|
||||
#define str_to_ipv6 bcstr_to_ipv6
|
||||
#include "sck-addr.h"
|
||||
|
||||
|
||||
static int str_to_sockaddr (mio_t* mio, const mio_ooch_t* str, mio_oow_t len, sockaddr_t* nwad)
|
||||
{
|
||||
const mio_ooch_t* p;
|
||||
const mio_ooch_t* end;
|
||||
mio_oocs_t tmp;
|
||||
|
||||
p = str;
|
||||
end = str + len;
|
||||
|
||||
if (p >= end)
|
||||
{
|
||||
mio_seterrbfmt (mio, MIO_EINVAL, "blank address");
|
||||
return -1;
|
||||
}
|
||||
|
||||
MIO_MEMSET (nwad, 0, MIO_SIZEOF(*nwad));
|
||||
|
||||
#if defined(AF_UNIX)
|
||||
if (*p == '/' && len >= 2)
|
||||
{
|
||||
#if defined(MIO_OOCH_IS_BCH)
|
||||
mio_copybcstr (nwad->un.sun_path, MIO_COUNTOF(nwad->un.sun_path), str);
|
||||
#else
|
||||
mio_oow_t dstlen;
|
||||
|
||||
dstlen = MIO_COUNTOF(nwad->un.sun_path) - 1;
|
||||
if (mio_convutobchars (mio, p, &len, nwad->un.sun_path, &dstlen) <= -1)
|
||||
{
|
||||
mio_seterrbfmt (mio, MIO_EINVAL, "unable to convert encoding");
|
||||
return -1;
|
||||
}
|
||||
nwad->un.sun_path[dstlen] = '\0';
|
||||
#endif
|
||||
nwad->un.sun_family = AF_UNIX;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (MIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0)
|
||||
if (*p == '[')
|
||||
{
|
||||
/* IPv6 address */
|
||||
tmp.ptr = (mio_ooch_t*)++p; /* skip [ and remember the position */
|
||||
while (p < end && *p != '%' && *p != ']') p++;
|
||||
|
||||
if (p >= end) goto no_rbrack;
|
||||
|
||||
tmp.len = p - tmp.ptr;
|
||||
if (*p == '%')
|
||||
{
|
||||
/* handle scope id */
|
||||
mio_uint32_t x;
|
||||
|
||||
p++; /* skip % */
|
||||
|
||||
if (p >= end)
|
||||
{
|
||||
/* premature end */
|
||||
mio_seterrbfmt (mio, MIO_EINVAL, "scope id blank");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (*p >= '0' && *p <= '9')
|
||||
{
|
||||
/* numeric scope id */
|
||||
nwad->in6.sin6_scope_id = 0;
|
||||
do
|
||||
{
|
||||
x = nwad->in6.sin6_scope_id * 10 + (*p - '0');
|
||||
if (x < nwad->in6.sin6_scope_id)
|
||||
{
|
||||
mio_seterrbfmt (mio, MIO_EINVAL, "scope id too large");
|
||||
return -1; /* overflow */
|
||||
}
|
||||
nwad->in6.sin6_scope_id = x;
|
||||
p++;
|
||||
}
|
||||
while (p < end && *p >= '0' && *p <= '9');
|
||||
}
|
||||
else
|
||||
{
|
||||
#if 0
|
||||
TODO:
|
||||
/* interface name as a scope id? */
|
||||
const mio_ooch_t* stmp = p;
|
||||
unsigned int index;
|
||||
do p++; while (p < end && *p != ']');
|
||||
if (mio_nwifwcsntoindex (stmp, p - stmp, &index) <= -1) return -1;
|
||||
tmpad.u.in6.scope = index;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (p >= end || *p != ']') goto no_rbrack;
|
||||
}
|
||||
p++; /* skip ] */
|
||||
|
||||
if (str_to_ipv6(tmp.ptr, tmp.len, &nwad->in6.sin6_addr) <= -1) goto unrecog;
|
||||
nwad->in6.sin6_family = AF_INET6;
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
/* IPv4 address */
|
||||
tmp.ptr = (mio_ooch_t*)p;
|
||||
while (p < end && *p != ':') p++;
|
||||
tmp.len = p - tmp.ptr;
|
||||
|
||||
if (str_to_ipv4(tmp.ptr, tmp.len, &nwad->in4.sin_addr) <= -1)
|
||||
{
|
||||
#if (MIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0)
|
||||
/* check if it is an IPv6 address not enclosed in [].
|
||||
* the port number can't be specified in this format. */
|
||||
if (p >= end || *p != ':')
|
||||
{
|
||||
/* without :, it can't be an ipv6 address */
|
||||
goto unrecog;
|
||||
}
|
||||
|
||||
|
||||
while (p < end && *p != '%') p++;
|
||||
tmp.len = p - tmp.ptr;
|
||||
|
||||
if (str_to_ipv6(tmp.ptr, tmp.len, &nwad->in6.sin6_addr) <= -1) goto unrecog;
|
||||
|
||||
if (p < end && *p == '%')
|
||||
{
|
||||
/* handle scope id */
|
||||
mio_uint32_t x;
|
||||
|
||||
p++; /* skip % */
|
||||
|
||||
if (p >= end)
|
||||
{
|
||||
/* premature end */
|
||||
mio_seterrbfmt (mio, MIO_EINVAL, "scope id blank");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (*p >= '0' && *p <= '9')
|
||||
{
|
||||
/* numeric scope id */
|
||||
nwad->in6.sin6_scope_id = 0;
|
||||
do
|
||||
{
|
||||
x = nwad->in6.sin6_scope_id * 10 + (*p - '0');
|
||||
if (x < nwad->in6.sin6_scope_id)
|
||||
{
|
||||
mio_seterrbfmt (mio, MIO_EINVAL, "scope id too large");
|
||||
return -1; /* overflow */
|
||||
}
|
||||
nwad->in6.sin6_scope_id = x;
|
||||
p++;
|
||||
}
|
||||
while (p < end && *p >= '0' && *p <= '9');
|
||||
}
|
||||
else
|
||||
{
|
||||
#if 0
|
||||
TODO
|
||||
/* interface name as a scope id? */
|
||||
const mio_ooch_t* stmp = p;
|
||||
unsigned int index;
|
||||
do p++; while (p < end);
|
||||
if (mio_nwifwcsntoindex (stmp, p - stmp, &index) <= -1) return -1;
|
||||
nwad->in6.sin6_scope_id = index;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (p < end) goto unrecog; /* some gargage after the end? */
|
||||
|
||||
nwad->in6.sin6_family = AF_INET6;
|
||||
return 0;
|
||||
#else
|
||||
goto unrecog;
|
||||
#endif
|
||||
}
|
||||
|
||||
nwad->in4.sin_family = AF_INET;
|
||||
#if (MIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (p < end && *p == ':')
|
||||
{
|
||||
/* port number */
|
||||
mio_uint32_t port = 0;
|
||||
|
||||
p++; /* skip : */
|
||||
|
||||
tmp.ptr = (mio_ooch_t*)p;
|
||||
while (p < end && *p >= '0' && *p <= '9')
|
||||
{
|
||||
port = port * 10 + (*p - '0');
|
||||
p++;
|
||||
}
|
||||
|
||||
tmp.len = p - tmp.ptr;
|
||||
if (tmp.len <= 0 || tmp.len >= 6 ||
|
||||
port > MIO_TYPE_MAX(mio_uint16_t))
|
||||
{
|
||||
mio_seterrbfmt (mio, MIO_EINVAL, "port number blank or too large");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if (MIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0)
|
||||
if (nwad->in4.sin_family == AF_INET)
|
||||
nwad->in4.sin_port = mio_hton16(port);
|
||||
else
|
||||
nwad->in6.sin6_port = mio_hton16(port);
|
||||
#else
|
||||
nwad->in4.sin_port = mio_hton16(port);
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
unrecog:
|
||||
mio_seterrbfmt (mio, MIO_EINVAL, "unrecognized address");
|
||||
return -1;
|
||||
|
||||
no_rbrack:
|
||||
mio_seterrbfmt (mio, MIO_EINVAL, "missing right bracket");
|
||||
return -1;
|
||||
}
|
||||
#undef char_t
|
||||
#undef cstr_t
|
||||
#undef str_to_sockaddr
|
||||
#undef str_to_ipv4
|
||||
#undef str_to_ipv6
|
||||
#undef CHAR_T_IS_BCH
|
||||
#define CHAR_T_IS_UCH
|
||||
#define char_t mio_uch_t
|
||||
#define cstr_t mio_ucs_t
|
||||
#define str_to_sockaddr ucstr_to_sockaddr
|
||||
#define str_to_ipv4 ucstr_to_ipv4
|
||||
#define str_to_ipv6 ucstr_to_ipv6
|
||||
#include "sck-addr.h"
|
||||
|
383
mio/lib/sck-addr.h
Normal file
383
mio/lib/sck-addr.h
Normal file
@ -0,0 +1,383 @@
|
||||
/* this file is included by sck-addr.c */
|
||||
|
||||
static int str_to_ipv4 (const char_t* str, mio_oow_t len, struct in_addr* inaddr)
|
||||
{
|
||||
const char_t* end;
|
||||
int dots = 0, digits = 0;
|
||||
mio_uint32_t acc = 0, addr = 0;
|
||||
char_t c;
|
||||
|
||||
end = str + len;
|
||||
|
||||
do
|
||||
{
|
||||
if (str >= end)
|
||||
{
|
||||
if (dots < 3 || digits == 0) return -1;
|
||||
addr = (addr << 8) | acc;
|
||||
break;
|
||||
}
|
||||
|
||||
c = *str++;
|
||||
|
||||
if (c >= '0' && c <= '9')
|
||||
{
|
||||
if (digits > 0 && acc == 0) return -1;
|
||||
acc = acc * 10 + (c - '0');
|
||||
if (acc > 255) return -1;
|
||||
digits++;
|
||||
}
|
||||
else if (c == '.')
|
||||
{
|
||||
if (dots >= 3 || digits == 0) return -1;
|
||||
addr = (addr << 8) | acc;
|
||||
dots++; acc = 0; digits = 0;
|
||||
}
|
||||
else return -1;
|
||||
}
|
||||
while (1);
|
||||
|
||||
inaddr->s_addr = mio_hton32(addr);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
#if (MIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0)
|
||||
static int str_to_ipv6 (const char_t* src, mio_oow_t len, struct in6_addr* inaddr)
|
||||
{
|
||||
mio_uint8_t* tp, * endp, * colonp;
|
||||
const char_t* curtok;
|
||||
char_t ch;
|
||||
int saw_xdigit;
|
||||
unsigned int val;
|
||||
const char_t* src_end;
|
||||
|
||||
src_end = src + len;
|
||||
|
||||
MIO_MEMSET (inaddr, 0, MIO_SIZEOF(*inaddr));
|
||||
tp = &inaddr->s6_addr[0];
|
||||
endp = &inaddr->s6_addr[MIO_COUNTOF(inaddr->s6_addr)];
|
||||
colonp = MIO_NULL;
|
||||
|
||||
/* Leading :: requires some special handling. */
|
||||
if (src < src_end && *src == ':')
|
||||
{
|
||||
src++;
|
||||
if (src >= src_end || *src != ':') return -1;
|
||||
}
|
||||
|
||||
curtok = src;
|
||||
saw_xdigit = 0;
|
||||
val = 0;
|
||||
|
||||
while (src < src_end)
|
||||
{
|
||||
int v1;
|
||||
|
||||
ch = *src++;
|
||||
|
||||
if (ch >= '0' && ch <= '9')
|
||||
v1 = ch - '0';
|
||||
else if (ch >= 'A' && ch <= 'F')
|
||||
v1 = ch - 'A' + 10;
|
||||
else if (ch >= 'a' && ch <= 'f')
|
||||
v1 = ch - 'a' + 10;
|
||||
else v1 = -1;
|
||||
if (v1 >= 0)
|
||||
{
|
||||
val <<= 4;
|
||||
val |= v1;
|
||||
if (val > 0xffff) return -1;
|
||||
saw_xdigit = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ch == ':')
|
||||
{
|
||||
curtok = src;
|
||||
if (!saw_xdigit)
|
||||
{
|
||||
if (colonp) return -1;
|
||||
colonp = tp;
|
||||
continue;
|
||||
}
|
||||
else if (src >= src_end)
|
||||
{
|
||||
/* a colon can't be the last character */
|
||||
return -1;
|
||||
}
|
||||
|
||||
*tp++ = (mio_uint8_t)(val >> 8) & 0xff;
|
||||
*tp++ = (mio_uint8_t)val & 0xff;
|
||||
saw_xdigit = 0;
|
||||
val = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ch == '.' && ((tp + MIO_SIZEOF(struct in_addr)) <= endp) &&
|
||||
str_to_ipv4(curtok, src_end - curtok, (struct in_addr*)tp) == 0)
|
||||
{
|
||||
tp += MIO_SIZEOF(struct in_addr*);
|
||||
saw_xdigit = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (saw_xdigit)
|
||||
{
|
||||
if (tp + MIO_SIZEOF(mio_uint16_t) > endp) return -1;
|
||||
*tp++ = (mio_uint8_t)(val >> 8) & 0xff;
|
||||
*tp++ = (mio_uint8_t)val & 0xff;
|
||||
}
|
||||
if (colonp != MIO_NULL)
|
||||
{
|
||||
/*
|
||||
* Since some memmove()'s erroneously fail to handle
|
||||
* overlapping regions, we'll do the shift by hand.
|
||||
*/
|
||||
mio_oow_t n = tp - colonp;
|
||||
mio_oow_t i;
|
||||
|
||||
for (i = 1; i <= n; i++)
|
||||
{
|
||||
endp[-i] = colonp[n - i];
|
||||
colonp[n - i] = 0;
|
||||
}
|
||||
tp = endp;
|
||||
}
|
||||
|
||||
if (tp != endp) return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static int str_to_sockaddr (mio_t* mio, const char_t* str, mio_oow_t len, sockaddr_t* nwad)
|
||||
{
|
||||
const char_t* p;
|
||||
const char_t* end;
|
||||
cstr_t tmp;
|
||||
|
||||
p = str;
|
||||
end = str + len;
|
||||
|
||||
if (p >= end)
|
||||
{
|
||||
mio_seterrbfmt (mio, MIO_EINVAL, "blank address");
|
||||
return -1;
|
||||
}
|
||||
|
||||
MIO_MEMSET (nwad, 0, MIO_SIZEOF(*nwad));
|
||||
|
||||
#if defined(AF_UNIX)
|
||||
if (*p == '/' && len >= 2)
|
||||
{
|
||||
#if defined(CHAR_T_IS_BCH)
|
||||
mio_copy_bcstr (nwad->un.sun_path, MIO_COUNTOF(nwad->un.sun_path), str);
|
||||
#else
|
||||
mio_oow_t dstlen;
|
||||
|
||||
dstlen = MIO_COUNTOF(nwad->un.sun_path) - 1;
|
||||
if (mio_convutobchars(mio, p, &len, nwad->un.sun_path, &dstlen) <= -1)
|
||||
{
|
||||
mio_seterrbfmt (mio, MIO_EINVAL, "unable to convert encoding");
|
||||
return -1;
|
||||
}
|
||||
nwad->un.sun_path[dstlen] = '\0';
|
||||
#endif
|
||||
nwad->un.sun_family = AF_UNIX;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (MIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0)
|
||||
if (*p == '[')
|
||||
{
|
||||
/* IPv6 address */
|
||||
tmp.ptr = (char_t*)++p; /* skip [ and remember the position */
|
||||
while (p < end && *p != '%' && *p != ']') p++;
|
||||
|
||||
if (p >= end) goto no_rbrack;
|
||||
|
||||
tmp.len = p - tmp.ptr;
|
||||
if (*p == '%')
|
||||
{
|
||||
/* handle scope id */
|
||||
mio_uint32_t x;
|
||||
|
||||
p++; /* skip % */
|
||||
|
||||
if (p >= end)
|
||||
{
|
||||
/* premature end */
|
||||
mio_seterrbfmt (mio, MIO_EINVAL, "scope id blank");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (*p >= '0' && *p <= '9')
|
||||
{
|
||||
/* numeric scope id */
|
||||
nwad->in6.sin6_scope_id = 0;
|
||||
do
|
||||
{
|
||||
x = nwad->in6.sin6_scope_id * 10 + (*p - '0');
|
||||
if (x < nwad->in6.sin6_scope_id)
|
||||
{
|
||||
mio_seterrbfmt (mio, MIO_EINVAL, "scope id too large");
|
||||
return -1; /* overflow */
|
||||
}
|
||||
nwad->in6.sin6_scope_id = x;
|
||||
p++;
|
||||
}
|
||||
while (p < end && *p >= '0' && *p <= '9');
|
||||
}
|
||||
else
|
||||
{
|
||||
#if 0
|
||||
TODO:
|
||||
/* interface name as a scope id? */
|
||||
const char_t* stmp = p;
|
||||
unsigned int index;
|
||||
do p++; while (p < end && *p != ']');
|
||||
if (mio_nwifwcsntoindex (stmp, p - stmp, &index) <= -1) return -1;
|
||||
tmpad.u.in6.scope = index;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (p >= end || *p != ']') goto no_rbrack;
|
||||
}
|
||||
p++; /* skip ] */
|
||||
|
||||
if (str_to_ipv6(tmp.ptr, tmp.len, &nwad->in6.sin6_addr) <= -1) goto unrecog;
|
||||
nwad->in6.sin6_family = AF_INET6;
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
/* IPv4 address */
|
||||
tmp.ptr = (char_t*)p;
|
||||
while (p < end && *p != ':') p++;
|
||||
tmp.len = p - tmp.ptr;
|
||||
|
||||
if (str_to_ipv4(tmp.ptr, tmp.len, &nwad->in4.sin_addr) <= -1)
|
||||
{
|
||||
#if (MIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0)
|
||||
/* check if it is an IPv6 address not enclosed in [].
|
||||
* the port number can't be specified in this format. */
|
||||
if (p >= end || *p != ':')
|
||||
{
|
||||
/* without :, it can't be an ipv6 address */
|
||||
goto unrecog;
|
||||
}
|
||||
|
||||
|
||||
while (p < end && *p != '%') p++;
|
||||
tmp.len = p - tmp.ptr;
|
||||
|
||||
if (str_to_ipv6(tmp.ptr, tmp.len, &nwad->in6.sin6_addr) <= -1) goto unrecog;
|
||||
|
||||
if (p < end && *p == '%')
|
||||
{
|
||||
/* handle scope id */
|
||||
mio_uint32_t x;
|
||||
|
||||
p++; /* skip % */
|
||||
|
||||
if (p >= end)
|
||||
{
|
||||
/* premature end */
|
||||
mio_seterrbfmt (mio, MIO_EINVAL, "scope id blank");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (*p >= '0' && *p <= '9')
|
||||
{
|
||||
/* numeric scope id */
|
||||
nwad->in6.sin6_scope_id = 0;
|
||||
do
|
||||
{
|
||||
x = nwad->in6.sin6_scope_id * 10 + (*p - '0');
|
||||
if (x < nwad->in6.sin6_scope_id)
|
||||
{
|
||||
mio_seterrbfmt (mio, MIO_EINVAL, "scope id too large");
|
||||
return -1; /* overflow */
|
||||
}
|
||||
nwad->in6.sin6_scope_id = x;
|
||||
p++;
|
||||
}
|
||||
while (p < end && *p >= '0' && *p <= '9');
|
||||
}
|
||||
else
|
||||
{
|
||||
#if 0
|
||||
TODO
|
||||
/* interface name as a scope id? */
|
||||
const char_t* stmp = p;
|
||||
unsigned int index;
|
||||
do p++; while (p < end);
|
||||
if (mio_nwifwcsntoindex (stmp, p - stmp, &index) <= -1) return -1;
|
||||
nwad->in6.sin6_scope_id = index;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (p < end) goto unrecog; /* some gargage after the end? */
|
||||
|
||||
nwad->in6.sin6_family = AF_INET6;
|
||||
return 0;
|
||||
#else
|
||||
goto unrecog;
|
||||
#endif
|
||||
}
|
||||
|
||||
nwad->in4.sin_family = AF_INET;
|
||||
#if (MIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (p < end && *p == ':')
|
||||
{
|
||||
/* port number */
|
||||
mio_uint32_t port = 0;
|
||||
|
||||
p++; /* skip : */
|
||||
|
||||
tmp.ptr = (char_t*)p;
|
||||
while (p < end && *p >= '0' && *p <= '9')
|
||||
{
|
||||
port = port * 10 + (*p - '0');
|
||||
p++;
|
||||
}
|
||||
|
||||
tmp.len = p - tmp.ptr;
|
||||
if (tmp.len <= 0 || tmp.len >= 6 ||
|
||||
port > MIO_TYPE_MAX(mio_uint16_t))
|
||||
{
|
||||
mio_seterrbfmt (mio, MIO_EINVAL, "port number blank or too large");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if (MIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0)
|
||||
if (nwad->in4.sin_family == AF_INET)
|
||||
nwad->in4.sin_port = mio_hton16(port);
|
||||
else
|
||||
nwad->in6.sin6_port = mio_hton16(port);
|
||||
#else
|
||||
nwad->in4.sin_port = mio_hton16(port);
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
unrecog:
|
||||
mio_seterrbfmt (mio, MIO_EINVAL, "unrecognized address");
|
||||
return -1;
|
||||
|
||||
no_rbrack:
|
||||
mio_seterrbfmt (mio, MIO_EINVAL, "missing right bracket");
|
||||
return -1;
|
||||
}
|
1368
mio/lib/utl.c
Normal file
1368
mio/lib/utl.c
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user