added intmax formatting functions

This commit is contained in:
hyung-hwan 2020-02-20 06:48:43 +00:00
parent e19490a505
commit e73d822d0a
10 changed files with 767 additions and 89 deletions

View File

@ -23,6 +23,7 @@ include_HEADERS = \
mio-cfg.h \ mio-cfg.h \
mio-cmn.h \ mio-cmn.h \
mio-dns.h \ mio-dns.h \
mio-fmt.h \
mio-nwif.h \ mio-nwif.h \
mio-pac1.h \ mio-pac1.h \
mio-pro.h \ mio-pro.h \
@ -37,6 +38,7 @@ libmio_la_SOURCES = \
dns.c \ dns.c \
err.c \ err.c \
fmt.c \ fmt.c \
fmt-imp.h \
mio-prv.h \ mio-prv.h \
mio-sys.h \ mio-sys.h \
mio.c \ mio.c \

View File

@ -398,6 +398,7 @@ include_HEADERS = \
mio-cfg.h \ mio-cfg.h \
mio-cmn.h \ mio-cmn.h \
mio-dns.h \ mio-dns.h \
mio-fmt.h \
mio-nwif.h \ mio-nwif.h \
mio-pac1.h \ mio-pac1.h \
mio-pro.h \ mio-pro.h \
@ -412,6 +413,7 @@ libmio_la_SOURCES = \
dns.c \ dns.c \
err.c \ err.c \
fmt.c \ fmt.c \
fmt-imp.h \
mio-prv.h \ mio-prv.h \
mio-sys.h \ mio-sys.h \
mio.c \ mio.c \

View File

@ -25,6 +25,7 @@
*/ */
#include "mio-prv.h" #include "mio-prv.h"
#include "mio-fmt.h"
static mio_ooch_t errstr_0[] = {'n', 'o', ' ', 'e', 'r', 'r', 'o', 'r', '\0' }; 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_1[] = {'g', 'e', 'n', 'e', 'r', 'i', 'c', ' ', 'e', 'r', 'r', 'o', 'r', '\0' };

228
mio/lib/fmt-imp.h Normal file
View File

@ -0,0 +1,228 @@
/*
* $Id$
*
Copyright (c) 2006-2019 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.
*/
static int fmt_uintmax (
char_t* buf, int size,
mio_uintmax_t value, int base_and_flags, int prec,
char_t fillchar, char_t signchar, const char_t* prefix)
{
char_t tmp[(MIO_SIZEOF(mio_uintmax_t) * 8)];
int reslen, base, fillsize, reqlen, pflen, preczero;
char_t* p, * bp, * be;
const mio_bch_t* xbasestr;
base = base_and_flags & 0x3F;
if (base < 2 || base > 36) return -1;
xbasestr = (base_and_flags & MIO_FMT_INTMAX_UPPERCASE)?
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ":
"0123456789abcdefghijklmnopqrstuvwxyz";
if ((base_and_flags & MIO_FMT_INTMAX_NOZERO) && value == 0)
{
p = tmp;
if (base_and_flags & MIO_FMT_INTMAX_ZEROLEAD)
{
/* NOZERO emits no digit, ZEROLEAD emits 1 digit.
* so it emits '0' */
reslen = 1;
preczero = 1;
}
else
{
/* since the value is zero, emit no digits */
reslen = 0;
preczero = 0;
}
}
else
{
mio_uintmax_t v = value;
/* store the resulting numeric string into 'tmp' first */
p = tmp;
do
{
*p++ = xbasestr[v % base];
v /= base;
}
while (v > 0);
/* reslen is the length of the resulting string without padding. */
reslen = (int)(p - tmp);
/* precision specified the minum number of digits to produce.
* so if the precision is larger that the digits produced,
* reslen should be adjusted to precision */
if (prec > reslen)
{
/* if the precision is greater than the actual digits
* made from the value, 0 is inserted in front.
* ZEROLEAD doesn't have to be handled explicitly
* since it's achieved effortlessly */
preczero = prec - reslen;
reslen = prec;
}
else
{
preczero = 0;
if ((base_and_flags & MIO_FMT_INTMAX_ZEROLEAD) && value != 0)
{
/* if value is zero, 0 is emitted from it.
* so ZEROLEAD don't need to add another 0. */
preczero++;
reslen++;
}
}
}
if (signchar) reslen++; /* increment reslen for the sign character */
if (prefix)
{
/* since the length can be truncated for different type sizes,
* don't pass in a very long prefix. */
const char_t* pp;
for (pp = prefix; *pp != '\0'; pp++) ;
pflen = pp - prefix;
reslen += pflen;
}
else pflen = 0;
/* get the required buffer size for lossless formatting */
reqlen = (base_and_flags & MIO_FMT_INTMAX_NONULL)? reslen: (reslen + 1);
if (size <= 0 ||
((base_and_flags & MIO_FMT_INTMAX_NOTRUNC) && size < reqlen))
{
return -reqlen;
}
/* get the size to fill with fill characters */
fillsize = (base_and_flags & MIO_FMT_INTMAX_NONULL)? size: (size - 1);
bp = buf;
be = buf + fillsize;
/* fill space */
if (fillchar != '\0')
{
if (base_and_flags & MIO_FMT_INTMAX_FILLRIGHT)
{
/* emit sign */
if (signchar && bp < be) *bp++ = signchar;
/* copy prefix if necessary */
if (prefix) while (*prefix && bp < be) *bp++ = *prefix++;
/* add 0s for precision */
while (preczero > 0 && bp < be)
{
*bp++ = '0';
preczero--;
}
/* copy the numeric string to the destination buffer */
while (p > tmp && bp < be) *bp++ = *--p;
/* fill the right side */
while (fillsize > reslen)
{
*bp++ = fillchar;
fillsize--;
}
}
else if (base_and_flags & MIO_FMT_INTMAX_FILLCENTER)
{
/* emit sign */
if (signchar && bp < be) *bp++ = signchar;
/* fill the left side */
while (fillsize > reslen)
{
*bp++ = fillchar;
fillsize--;
}
/* copy prefix if necessary */
if (prefix) while (*prefix && bp < be) *bp++ = *prefix++;
/* add 0s for precision */
while (preczero > 0 && bp < be)
{
*bp++ = '0';
preczero--;
}
/* copy the numeric string to the destination buffer */
while (p > tmp && bp < be) *bp++ = *--p;
}
else
{
/* fill the left side */
while (fillsize > reslen)
{
*bp++ = fillchar;
fillsize--;
}
/* emit sign */
if (signchar && bp < be) *bp++ = signchar;
/* copy prefix if necessary */
if (prefix) while (*prefix && bp < be) *bp++ = *prefix++;
/* add 0s for precision */
while (preczero > 0 && bp < be)
{
*bp++ = '0';
preczero--;
}
/* copy the numeric string to the destination buffer */
while (p > tmp && bp < be) *bp++ = *--p;
}
}
else
{
/* emit sign */
if (signchar && bp < be) *bp++ = signchar;
/* copy prefix if necessary */
if (prefix) while (*prefix && bp < be) *bp++ = *prefix++;
/* add 0s for precision */
while (preczero > 0 && bp < be)
{
*bp++ = '0';
preczero--;
}
/* copy the numeric string to the destination buffer */
while (p > tmp && bp < be) *bp++ = *--p;
}
if (!(base_and_flags & MIO_FMT_INTMAX_NONULL)) *bp = '\0';
return bp - buf;
}

View File

@ -64,7 +64,7 @@
* *
*/ */
#include "mio-fmt.h"
#include "mio-prv.h" #include "mio-prv.h"
@ -1615,3 +1615,136 @@ mio_ooi_t mio_logufmt (mio_t* mio, mio_bitmask_t mask, const mio_uch_t* fmt, ...
return x; return x;
} }
/* ------------------------------------------------------------------------------------- */
/*define static int fmt_uintmax_to_bcstr(...)*/
#undef char_t
#undef fmt_uintmax
#define char_t mio_bch_t
#define fmt_uintmax fmt_uintmax_to_bcstr
#include "fmt-imp.h"
/*define static int fmt_uintmax_to_ucstr(...)*/
#undef char_t
#undef fmt_uintmax
#define char_t mio_uch_t
#define fmt_uintmax fmt_uintmax_to_ucstr
#include "fmt-imp.h"
/* ------------------------------------------------------------------------------------- */
int mio_fmt_intmax_to_bcstr (
mio_bch_t* buf, int size,
mio_intmax_t value, int base_and_flags, int prec,
mio_bch_t fillchar, const mio_bch_t* prefix)
{
mio_bch_t signchar;
mio_uintmax_t absvalue;
if (value < 0)
{
signchar = '-';
absvalue = -value;
}
else if (base_and_flags & MIO_FMT_INTMAX_TO_BCSTR_PLUSSIGN)
{
signchar = '+';
absvalue = value;
}
else if (base_and_flags & MIO_FMT_INTMAX_TO_BCSTR_EMPTYSIGN)
{
signchar = ' ';
absvalue = value;
}
else
{
signchar = '\0';
absvalue = value;
}
return fmt_uintmax_to_bcstr(buf, size, absvalue, base_and_flags, prec, fillchar, signchar, prefix);
}
int mio_fmt_uintmax_to_bcstr (
mio_bch_t* buf, int size,
mio_uintmax_t value, int base_and_flags, int prec,
mio_bch_t fillchar, const mio_bch_t* prefix)
{
mio_bch_t signchar;
/* determine if a sign character is needed */
if (base_and_flags & MIO_FMT_INTMAX_TO_BCSTR_PLUSSIGN)
{
signchar = '+';
}
else if (base_and_flags & MIO_FMT_INTMAX_TO_BCSTR_EMPTYSIGN)
{
signchar = ' ';
}
else
{
signchar = '\0';
}
return fmt_uintmax_to_bcstr(buf, size, value, base_and_flags, prec, fillchar, signchar, prefix);
}
/* ------------------------------------------------------------------------------------- */
int mio_fmt_intmax_to_ucstr (
mio_uch_t* buf, int size,
mio_intmax_t value, int base_and_flags, int prec,
mio_uch_t fillchar, const mio_uch_t* prefix)
{
mio_uch_t signchar;
mio_uintmax_t absvalue;
if (value < 0)
{
signchar = '-';
absvalue = -value;
}
else if (base_and_flags & MIO_FMT_INTMAX_TO_UCSTR_PLUSSIGN)
{
signchar = '+';
absvalue = value;
}
else if (base_and_flags & MIO_FMT_INTMAX_TO_UCSTR_EMPTYSIGN)
{
signchar = ' ';
absvalue = value;
}
else
{
signchar = '\0';
absvalue = value;
}
return fmt_uintmax_to_ucstr(buf, size, absvalue, base_and_flags, prec, fillchar, signchar, prefix);
}
int mio_fmt_uintmax_to_ucstr (
mio_uch_t* buf, int size,
mio_uintmax_t value, int base_and_flags, int prec,
mio_uch_t fillchar, const mio_uch_t* prefix)
{
mio_uch_t signchar;
/* determine if a sign character is needed */
if (base_and_flags & MIO_FMT_INTMAX_TO_UCSTR_PLUSSIGN)
{
signchar = '+';
}
else if (base_and_flags & MIO_FMT_INTMAX_TO_UCSTR_EMPTYSIGN)
{
signchar = ' ';
}
else
{
signchar = '\0';
}
return fmt_uintmax_to_ucstr(buf, size, value, base_and_flags, prec, fillchar, signchar, prefix);
}

View File

@ -428,6 +428,8 @@ typedef struct mio_bcs_t mio_bcs_t;
/* the maximum number of bch charaters to represent a single uch character */ /* the maximum number of bch charaters to represent a single uch character */
#define MIO_BCSIZE_MAX 6 #define MIO_BCSIZE_MAX 6
typedef unsigned int mio_bitmask_t;
/* ========================================================================= /* =========================================================================
* TIME-RELATED TYPES * TIME-RELATED TYPES
* =========================================================================*/ * =========================================================================*/

389
mio/lib/mio-fmt.h Normal file
View File

@ -0,0 +1,389 @@
/*
* $Id$
*
Copyright (c) 2006-2019 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_FMT_H_
#define _MIO_FMT_H_
#include <mio-cmn.h>
#include <stdarg.h>
/** \file
* This file defines various formatting functions.
*/
/* =========================================================================
* FORMATTED OUTPUT
* ========================================================================= */
typedef struct mio_fmtout_t mio_fmtout_t;
typedef int (*mio_fmtout_putbcs_t) (
mio_fmtout_t* fmtout,
const mio_bch_t* ptr,
mio_oow_t len
);
typedef int (*mio_fmtout_putucs_t) (
mio_fmtout_t* fmtout,
const mio_uch_t* ptr,
mio_oow_t len
);
enum mio_fmtout_fmt_type_t
{
MIO_FMTOUT_FMT_TYPE_BCH = 0,
MIO_FMTOUT_FMT_TYPE_UCH
};
typedef enum mio_fmtout_fmt_type_t mio_fmtout_fmt_type_t;
struct mio_fmtout_t
{
mio_oow_t count; /* out */
mio_fmtout_putbcs_t putbcs; /* in */
mio_fmtout_putucs_t putucs; /* in */
mio_bitmask_t mask; /* in */
void* ctx; /* in */
mio_fmtout_fmt_type_t fmt_type;
const void* fmt_str;
};
/* =========================================================================
* INTMAX FORMATTING
* ========================================================================= */
/**
* The mio_fmt_intmax_flag_t type defines enumerators to change the
* behavior of mio_fmt_intmax() and mio_fmt_uintmax().
*/
enum mio_fmt_intmax_flag_t
{
/* Use lower 6 bits to represent base between 2 and 36 inclusive.
* Upper bits are used for these flag options */
/** Don't truncate if the buffer is not large enough */
MIO_FMT_INTMAX_NOTRUNC = (0x40 << 0),
#define MIO_FMT_INTMAX_NOTRUNC MIO_FMT_INTMAX_NOTRUNC
#define MIO_FMT_UINTMAX_NOTRUNC MIO_FMT_INTMAX_NOTRUNC
#define MIO_FMT_INTMAX_TO_BCSTR_NOTRUNC MIO_FMT_INTMAX_NOTRUNC
#define MIO_FMT_UINTMAX_TO_BCSTR_NOTRUNC MIO_FMT_INTMAX_NOTRUNC
#define MIO_FMT_INTMAX_TO_UCSTR_NOTRUNC MIO_FMT_INTMAX_NOTRUNC
#define MIO_FMT_UINTMAX_TO_UCSTR_NOTRUNC MIO_FMT_INTMAX_NOTRUNC
#define MIO_FMT_INTMAX_TO_OOCSTR_NOTRUNC MIO_FMT_INTMAX_NOTRUNC
#define MIO_FMT_UINTMAX_TO_OOCSTR_NOTRUNC MIO_FMT_INTMAX_NOTRUNC
/** Don't append a terminating null */
MIO_FMT_INTMAX_NONULL = (0x40 << 1),
#define MIO_FMT_INTMAX_NONULL MIO_FMT_INTMAX_NONULL
#define MIO_FMT_UINTMAX_NONULL MIO_FMT_INTMAX_NONULL
#define MIO_FMT_INTMAX_TO_BCSTR_NONULL MIO_FMT_INTMAX_NONULL
#define MIO_FMT_UINTMAX_TO_BCSTR_NONULL MIO_FMT_INTMAX_NONULL
#define MIO_FMT_INTMAX_TO_UCSTR_NONULL MIO_FMT_INTMAX_NONULL
#define MIO_FMT_UINTMAX_TO_UCSTR_NONULL MIO_FMT_INTMAX_NONULL
#define MIO_FMT_INTMAX_TO_OOCSTR_NONULL MIO_FMT_INTMAX_NONULL
#define MIO_FMT_UINTMAX_TO_OOCSTR_NONULL MIO_FMT_INTMAX_NONULL
/** Produce no digit for a value of zero */
MIO_FMT_INTMAX_NOZERO = (0x40 << 2),
#define MIO_FMT_INTMAX_NOZERO MIO_FMT_INTMAX_NOZERO
#define MIO_FMT_UINTMAX_NOZERO MIO_FMT_INTMAX_NOZERO
#define MIO_FMT_INTMAX_TO_BCSTR_NOZERO MIO_FMT_INTMAX_NOZERO
#define MIO_FMT_UINTMAX_TO_BCSTR_NOZERO MIO_FMT_INTMAX_NOZERO
#define MIO_FMT_INTMAX_TO_UCSTR_NOZERO MIO_FMT_INTMAX_NOZERO
#define MIO_FMT_UINTMAX_TO_UCSTR_NOZERO MIO_FMT_INTMAX_NOZERO
#define MIO_FMT_INTMAX_TO_OOCSTR_NOZERO MIO_FMT_INTMAX_NOZERO
#define MIO_FMT_UINTMAX_TO_OOCSTR_NOZERO MIO_FMT_INTMAX_NOZERO
/** Produce a leading zero for a non-zero value */
MIO_FMT_INTMAX_ZEROLEAD = (0x40 << 3),
#define MIO_FMT_INTMAX_ZEROLEAD MIO_FMT_INTMAX_ZEROLEAD
#define MIO_FMT_UINTMAX_ZEROLEAD MIO_FMT_INTMAX_ZEROLEAD
#define MIO_FMT_INTMAX_TO_BCSTR_ZEROLEAD MIO_FMT_INTMAX_ZEROLEAD
#define MIO_FMT_UINTMAX_TO_BCSTR_ZEROLEAD MIO_FMT_INTMAX_ZEROLEAD
#define MIO_FMT_INTMAX_TO_UCSTR_ZEROLEAD MIO_FMT_INTMAX_ZEROLEAD
#define MIO_FMT_UINTMAX_TO_UCSTR_ZEROLEAD MIO_FMT_INTMAX_ZEROLEAD
#define MIO_FMT_INTMAX_TO_OOCSTR_ZEROLEAD MIO_FMT_INTMAX_ZEROLEAD
#define MIO_FMT_UINTMAX_TO_OOCSTR_ZEROLEAD MIO_FMT_INTMAX_ZEROLEAD
/** Use uppercase letters for alphabetic digits */
MIO_FMT_INTMAX_UPPERCASE = (0x40 << 4),
#define MIO_FMT_INTMAX_UPPERCASE MIO_FMT_INTMAX_UPPERCASE
#define MIO_FMT_UINTMAX_UPPERCASE MIO_FMT_INTMAX_UPPERCASE
#define MIO_FMT_INTMAX_TO_BCSTR_UPPERCASE MIO_FMT_INTMAX_UPPERCASE
#define MIO_FMT_UINTMAX_TO_BCSTR_UPPERCASE MIO_FMT_INTMAX_UPPERCASE
#define MIO_FMT_INTMAX_TO_UCSTR_UPPERCASE MIO_FMT_INTMAX_UPPERCASE
#define MIO_FMT_UINTMAX_TO_UCSTR_UPPERCASE MIO_FMT_INTMAX_UPPERCASE
#define MIO_FMT_INTMAX_TO_OOCSTR_UPPERCASE MIO_FMT_INTMAX_UPPERCASE
#define MIO_FMT_UINTMAX_TO_OOCSTR_UPPERCASE MIO_FMT_INTMAX_UPPERCASE
/** Insert a plus sign for a positive integer including 0 */
MIO_FMT_INTMAX_PLUSSIGN = (0x40 << 5),
#define MIO_FMT_INTMAX_PLUSSIGN MIO_FMT_INTMAX_PLUSSIGN
#define MIO_FMT_UINTMAX_PLUSSIGN MIO_FMT_INTMAX_PLUSSIGN
#define MIO_FMT_INTMAX_TO_BCSTR_PLUSSIGN MIO_FMT_INTMAX_PLUSSIGN
#define MIO_FMT_UINTMAX_TO_BCSTR_PLUSSIGN MIO_FMT_INTMAX_PLUSSIGN
#define MIO_FMT_INTMAX_TO_UCSTR_PLUSSIGN MIO_FMT_INTMAX_PLUSSIGN
#define MIO_FMT_UINTMAX_TO_UCSTR_PLUSSIGN MIO_FMT_INTMAX_PLUSSIGN
#define MIO_FMT_INTMAX_TO_OOCSTR_PLUSSIGN MIO_FMT_INTMAX_PLUSSIGN
#define MIO_FMT_UINTMAX_TO_OOCSTR_PLUSSIGN MIO_FMT_INTMAX_PLUSSIGN
/** Insert a space for a positive integer including 0 */
MIO_FMT_INTMAX_EMPTYSIGN = (0x40 << 6),
#define MIO_FMT_INTMAX_EMPTYSIGN MIO_FMT_INTMAX_EMPTYSIGN
#define MIO_FMT_UINTMAX_EMPTYSIGN MIO_FMT_INTMAX_EMPTYSIGN
#define MIO_FMT_INTMAX_TO_BCSTR_EMPTYSIGN MIO_FMT_INTMAX_EMPTYSIGN
#define MIO_FMT_UINTMAX_TO_BCSTR_EMPTYSIGN MIO_FMT_INTMAX_EMPTYSIGN
#define MIO_FMT_INTMAX_TO_UCSTR_EMPTYSIGN MIO_FMT_INTMAX_EMPTYSIGN
#define MIO_FMT_UINTMAX_TO_UCSTR_EMPTYSIGN MIO_FMT_INTMAX_EMPTYSIGN
/** Fill the right part of the string */
MIO_FMT_INTMAX_FILLRIGHT = (0x40 << 7),
#define MIO_FMT_INTMAX_FILLRIGHT MIO_FMT_INTMAX_FILLRIGHT
#define MIO_FMT_UINTMAX_FILLRIGHT MIO_FMT_INTMAX_FILLRIGHT
#define MIO_FMT_INTMAX_TO_BCSTR_FILLRIGHT MIO_FMT_INTMAX_FILLRIGHT
#define MIO_FMT_UINTMAX_TO_BCSTR_FILLRIGHT MIO_FMT_INTMAX_FILLRIGHT
#define MIO_FMT_INTMAX_TO_UCSTR_FILLRIGHT MIO_FMT_INTMAX_FILLRIGHT
#define MIO_FMT_UINTMAX_TO_UCSTR_FILLRIGHT MIO_FMT_INTMAX_FILLRIGHT
#define MIO_FMT_INTMAX_TO_OOCSTR_FILLRIGHT MIO_FMT_INTMAX_FILLRIGHT
#define MIO_FMT_UINTMAX_TO_OOCSTR_FILLRIGHT MIO_FMT_INTMAX_FILLRIGHT
/** Fill between the sign chacter and the digit part */
MIO_FMT_INTMAX_FILLCENTER = (0x40 << 8)
#define MIO_FMT_INTMAX_FILLCENTER MIO_FMT_INTMAX_FILLCENTER
#define MIO_FMT_UINTMAX_FILLCENTER MIO_FMT_INTMAX_FILLCENTER
#define MIO_FMT_INTMAX_TO_BCSTR_FILLCENTER MIO_FMT_INTMAX_FILLCENTER
#define MIO_FMT_UINTMAX_TO_BCSTR_FILLCENTER MIO_FMT_INTMAX_FILLCENTER
#define MIO_FMT_INTMAX_TO_UCSTR_FILLCENTER MIO_FMT_INTMAX_FILLCENTER
#define MIO_FMT_UINTMAX_TO_UCSTR_FILLCENTER MIO_FMT_INTMAX_FILLCENTER
#define MIO_FMT_INTMAX_TO_OOCSTR_FILLCENTER MIO_FMT_INTMAX_FILLCENTER
#define MIO_FMT_UINTMAX_TO_OOCSTR_FILLCENTER MIO_FMT_INTMAX_FILLCENTER
};
#if defined(__cplusplus)
extern "C" {
#endif
/* =========================================================================
* FORMATTED OUTPUT
* ========================================================================= */
MIO_EXPORT int mio_bfmt_outv (
mio_fmtout_t* fmtout,
const mio_bch_t* fmt,
va_list ap
);
MIO_EXPORT int mio_ufmt_outv (
mio_fmtout_t* fmtout,
const mio_uch_t* fmt,
va_list ap
);
MIO_EXPORT int mio_bfmt_out (
mio_fmtout_t* fmtout,
const mio_bch_t* fmt,
...
);
MIO_EXPORT int mio_ufmt_out (
mio_fmtout_t* fmtout,
const mio_uch_t* fmt,
...
);
/* =========================================================================
* INTMAX FORMATTING
* ========================================================================= */
/**
* The mio_fmt_intmax_to_bcstr() function formats an integer \a value to a
* multibyte string according to the given base and writes it to a buffer
* pointed to by \a buf. It writes to the buffer at most \a size characters
* including the terminating null. The base must be between 2 and 36 inclusive
* and can be ORed with zero or more #mio_fmt_intmax_to_bcstr_flag_t enumerators.
* This ORed value is passed to the function via the \a base_and_flags
* parameter. If the formatted string is shorter than \a bufsize, the redundant
* slots are filled with the fill character \a fillchar if it is not a null
* character. The filling behavior is determined by the flags shown below:
*
* - If #MIO_FMT_INTMAX_TO_BCSTR_FILLRIGHT is set in \a base_and_flags, slots
* after the formatting string are filled.
* - If #MIO_FMT_INTMAX_TO_BCSTR_FILLCENTER is set in \a base_and_flags, slots
* before the formatting string are filled. However, if it contains the
* sign character, the slots between the sign character and the digit part
* are filled.
* - If neither #MIO_FMT_INTMAX_TO_BCSTR_FILLRIGHT nor #MIO_FMT_INTMAX_TO_BCSTR_FILLCENTER
* , slots before the formatting string are filled.
*
* The \a precision parameter specified the minimum number of digits to
* produce from the \a value. If \a value produces fewer digits than
* \a precision, the actual digits are padded with '0' to meet the precision
* requirement. You can pass a negative number if you don't wish to specify
* precision.
*
* The terminating null is not added if #MIO_FMT_INTMAX_TO_BCSTR_NONULL is set;
* The #MIO_FMT_INTMAX_TO_BCSTR_UPPERCASE flag indicates that the function should
* use the uppercase letter for a alphabetic digit;
* You can set #MIO_FMT_INTMAX_TO_BCSTR_NOTRUNC if you require lossless formatting.
* The #MIO_FMT_INTMAX_TO_BCSTR_PLUSSIGN flag and #MIO_FMT_INTMAX_TO_BCSTR_EMPTYSIGN
* ensures that the plus sign and a space is added for a positive integer
* including 0 respectively.
* The #MIO_FMT_INTMAX_TO_BCSTR_ZEROLEAD flag ensures that the numeric string
* begins with '0' before applying the prefix.
* You can set the #MIO_FMT_INTMAX_TO_BCSTR_NOZERO flag if you want the value of
* 0 to produce nothing. If both #MIO_FMT_INTMAX_TO_BCSTR_NOZERO and
* #MIO_FMT_INTMAX_TO_BCSTR_ZEROLEAD are specified, '0' is still produced.
*
* If \a prefix is not #MIO_NULL, it is inserted before the digits.
*
* \return
* - -1 if the base is not between 2 and 36 inclusive.
* - negated number of characters required for lossless formatting
* - if \a bufsize is 0.
* - if #MIO_FMT_INTMAX_TO_BCSTR_NOTRUNC is set and \a bufsize is less than
* the minimum required for lossless formatting.
* - number of characters written to the buffer excluding a terminating
* null in all other cases.
*/
MIO_EXPORT int mio_fmt_intmax_to_bcstr (
mio_bch_t* buf, /**< buffer pointer */
int bufsize, /**< buffer size */
mio_intmax_t value, /**< integer to format */
int base_and_flags, /**< base ORed with flags */
int precision, /**< precision */
mio_bch_t fillchar, /**< fill character */
const mio_bch_t* prefix /**< prefix */
);
/**
* The mio_fmt_intmax_to_ucstr() function formats an integer \a value to a
* wide-character string according to the given base and writes it to a buffer
* pointed to by \a buf. It writes to the buffer at most \a size characters
* including the terminating null. The base must be between 2 and 36 inclusive
* and can be ORed with zero or more #mio_fmt_intmax_to_ucstr_flag_t enumerators.
* This ORed value is passed to the function via the \a base_and_flags
* parameter. If the formatted string is shorter than \a bufsize, the redundant
* slots are filled with the fill character \a fillchar if it is not a null
* character. The filling behavior is determined by the flags shown below:
*
* - If #MIO_FMT_INTMAX_TO_UCSTR_FILLRIGHT is set in \a base_and_flags, slots
* after the formatting string are filled.
* - If #MIO_FMT_INTMAX_TO_UCSTR_FILLCENTER is set in \a base_and_flags, slots
* before the formatting string are filled. However, if it contains the
* sign character, the slots between the sign character and the digit part
* are filled.
* - If neither #MIO_FMT_INTMAX_TO_UCSTR_FILLRIGHT nor #MIO_FMT_INTMAX_TO_UCSTR_FILLCENTER
* , slots before the formatting string are filled.
*
* The \a precision parameter specified the minimum number of digits to
* produce from the \ value. If \a value produces fewer digits than
* \a precision, the actual digits are padded with '0' to meet the precision
* requirement. You can pass a negative number if don't wish to specify
* precision.
*
* The terminating null is not added if #MIO_FMT_INTMAX_TO_UCSTR_NONULL is set;
* The #MIO_FMT_INTMAX_TO_UCSTR_UPPERCASE flag indicates that the function should
* use the uppercase letter for a alphabetic digit;
* You can set #MIO_FMT_INTMAX_TO_UCSTR_NOTRUNC if you require lossless formatting.
* The #MIO_FMT_INTMAX_TO_UCSTR_PLUSSIGN flag and #MIO_FMT_INTMAX_TO_UCSTR_EMPTYSIGN
* ensures that the plus sign and a space is added for a positive integer
* including 0 respectively.
* The #MIO_FMT_INTMAX_TO_UCSTR_ZEROLEAD flag ensures that the numeric string
* begins with 0 before applying the prefix.
* You can set the #MIO_FMT_INTMAX_TO_UCSTR_NOZERO flag if you want the value of
* 0 to produce nothing. If both #MIO_FMT_INTMAX_TO_UCSTR_NOZERO and
* #MIO_FMT_INTMAX_TO_UCSTR_ZEROLEAD are specified, '0' is still produced.
*
* If \a prefix is not #MIO_NULL, it is inserted before the digits.
*
* \return
* - -1 if the base is not between 2 and 36 inclusive.
* - negated number of characters required for lossless formatting
* - if \a bufsize is 0.
* - if #MIO_FMT_INTMAX_TO_UCSTR_NOTRUNC is set and \a bufsize is less than
* the minimum required for lossless formatting.
* - number of characters written to the buffer excluding a terminating
* null in all other cases.
*/
MIO_EXPORT int mio_fmt_intmax_to_ucstr (
mio_uch_t* buf, /**< buffer pointer */
int bufsize, /**< buffer size */
mio_intmax_t value, /**< integer to format */
int base_and_flags, /**< base ORed with flags */
int precision, /**< precision */
mio_uch_t fillchar, /**< fill character */
const mio_uch_t* prefix /**< prefix */
);
/**
* The mio_fmt_uintmax_to_bcstr() function formats an unsigned integer \a value
* to a multibyte string buffer. It behaves the same as mio_fmt_intmax_to_bcstr()
* except that it handles an unsigned integer.
*/
MIO_EXPORT int mio_fmt_uintmax_to_bcstr (
mio_bch_t* buf, /**< buffer pointer */
int bufsize, /**< buffer size */
mio_uintmax_t value, /**< integer to format */
int base_and_flags, /**< base ORed with flags */
int precision, /**< precision */
mio_bch_t fillchar, /**< fill character */
const mio_bch_t* prefix /**< prefix */
);
/**
* The mio_fmt_uintmax_to_ucstr() function formats an unsigned integer \a value
* to a unicode string buffer. It behaves the same as mio_fmt_intmax_to_ucstr()
* except that it handles an unsigned integer.
*/
MIO_EXPORT int mio_fmt_uintmax_to_ucstr (
mio_uch_t* buf, /**< buffer pointer */
int bufsize, /**< buffer size */
mio_uintmax_t value, /**< integer to format */
int base_and_flags, /**< base ORed with flags */
int precision, /**< precision */
mio_uch_t fillchar, /**< fill character */
const mio_uch_t* prefix /**< prefix */
);
#if defined(MIO_OOCH_IS_BCH)
# define mio_fmt_intmax_to_oocstr mio_fmt_intmax_to_bcstr
# define mio_fmt_uintmax_to_oocstr mio_fmt_uintmax_to_bcstr
#else
# define mio_fmt_intmax_to_oocstr mio_fmt_intmax_to_ucstr
# define mio_fmt_uintmax_to_oocstr mio_fmt_uintmax_to_ucstr
#endif
/* TODO: mio_fmt_fltmax_to_bcstr()... mio_fmt_fltmax_to_ucstr() */
#if defined(__cplusplus)
}
#endif
#endif

View File

@ -155,45 +155,6 @@
# error UNKNOWN ENDIAN # error UNKNOWN ENDIAN
#endif #endif
/* =========================================================================
* FORMATTED OUTPUT
* ========================================================================= */
typedef struct mio_fmtout_t mio_fmtout_t;
typedef int (*mio_fmtout_putbcs_t) (
mio_fmtout_t* fmtout,
const mio_bch_t* ptr,
mio_oow_t len
);
typedef int (*mio_fmtout_putucs_t) (
mio_fmtout_t* fmtout,
const mio_uch_t* ptr,
mio_oow_t len
);
enum mio_fmtout_fmt_type_t
{
MIO_FMTOUT_FMT_TYPE_BCH = 0,
MIO_FMTOUT_FMT_TYPE_UCH
};
typedef enum mio_fmtout_fmt_type_t mio_fmtout_fmt_type_t;
struct mio_fmtout_t
{
mio_oow_t count; /* out */
mio_fmtout_putbcs_t putbcs; /* in */
mio_fmtout_putucs_t putucs; /* in */
mio_bitmask_t mask; /* in */
void* ctx; /* in */
mio_fmtout_fmt_type_t fmt_type;
const void* fmt_str;
};
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -609,35 +570,6 @@ MIO_EXPORT mio_oow_t mio_utf8_to_uc (
mio_uch_t* uc mio_uch_t* uc
); );
/* =========================================================================
* FORMATTED OUTPUT
* ========================================================================= */
MIO_EXPORT int mio_bfmt_outv (
mio_fmtout_t* fmtout,
const mio_bch_t* fmt,
va_list ap
);
MIO_EXPORT int mio_ufmt_outv (
mio_fmtout_t* fmtout,
const mio_uch_t* fmt,
va_list ap
);
MIO_EXPORT int mio_bfmt_out (
mio_fmtout_t* fmtout,
const mio_bch_t* fmt,
...
);
MIO_EXPORT int mio_ufmt_out (
mio_fmtout_t* fmtout,
const mio_uch_t* fmt,
...
);
/* ========================================================================= /* =========================================================================
* BIT SWAP * BIT SWAP
* ========================================================================= */ * ========================================================================= */

View File

@ -63,8 +63,6 @@ typedef struct mio_wq_t mio_wq_t;
typedef struct mio_cwq_t mio_cwq_t; typedef struct mio_cwq_t mio_cwq_t;
typedef mio_intptr_t mio_iolen_t; /* NOTE: this is a signed type */ typedef mio_intptr_t mio_iolen_t; /* NOTE: this is a signed type */
typedef unsigned int mio_bitmask_t;
enum mio_errnum_t enum mio_errnum_t
{ {
MIO_ENOERR, /**< no error */ MIO_ENOERR, /**< no error */

View File

@ -26,6 +26,7 @@
#include "mio-skad.h" #include "mio-skad.h"
#include "mio-nwif.h" #include "mio-nwif.h"
#include "mio-fmt.h"
#include "mio-prv.h" #include "mio-prv.h"
#include <sys/types.h> #include <sys/types.h>
@ -945,7 +946,7 @@ static mio_oow_t ip6addr_to_ucstr (const struct in6_addr* ipad, mio_uch_t* buf,
break; break;
} }
/* TODO tp += mio_fmt_uintmax_to_ucstr(tp, MIO_COUNTOF(tmp) - (tp - tmp), words[i], 16, 0, '\0', MIO_NULL); */ tp += mio_fmt_uintmax_to_ucstr(tp, MIO_COUNTOF(tmp) - (tp - tmp), words[i], 16, 0, '\0', MIO_NULL);
} }
/* Was it a trailing run of 0x00's? */ /* Was it a trailing run of 0x00's? */
@ -985,7 +986,7 @@ mio_oow_t mio_skadtoucstr (mio_t* mio, const mio_skad_t* _skad, mio_uch_t* buf,
} }
if (xlen + 1 >= len) goto done; if (xlen + 1 >= len) goto done;
/* TODO xlen += mio_fmt_uintmax_to_ucstr(&buf[xlen], len - xlen, mio_ntoh16(skad->in4.sin_port), 10, 0, '\0', MIO_NULL); */ xlen += mio_fmt_uintmax_to_ucstr(&buf[xlen], len - xlen, mio_ntoh16(skad->in4.sin_port), 10, 0, '\0', MIO_NULL);
} }
} }
break; break;
@ -1020,7 +1021,7 @@ mio_oow_t mio_skadtoucstr (mio_t* mio, const mio_skad_t* _skad, mio_uch_t* buf,
tmp = mio_ifindextoucstr(mio, skad->in6.sin6_scope_id, &buf[xlen], len - xlen); tmp = mio_ifindextoucstr(mio, skad->in6.sin6_scope_id, &buf[xlen], len - xlen);
if (tmp <= -1) if (tmp <= -1)
{ {
/* TODO xlen += mio_fmt_uintmax_to_ucstr(&buf[xlen], len - xlen, skad->in6.sin6_scope_id, 10, 0, '\0', MIO_NULL); */ xlen += mio_fmt_uintmax_to_ucstr(&buf[xlen], len - xlen, skad->in6.sin6_scope_id, 10, 0, '\0', MIO_NULL);
} }
else xlen += tmp; else xlen += tmp;
} }
@ -1040,7 +1041,7 @@ mio_oow_t mio_skadtoucstr (mio_t* mio, const mio_skad_t* _skad, mio_uch_t* buf,
} }
if (xlen + 1 >= len) goto done; if (xlen + 1 >= len) goto done;
/* TODO xlen += mio_fmt_uintmax_to_ucstr(&buf[xlen], len - xlen, mio_ntoh16(skad->in6.sin6_port), 10, 0, '\0', MIO_NULL); */ xlen += mio_fmt_uintmax_to_ucstr(&buf[xlen], len - xlen, mio_ntoh16(skad->in6.sin6_port), 10, 0, '\0', MIO_NULL);
} }
} }
@ -1191,7 +1192,7 @@ static mio_oow_t ip6addr_to_bcstr (const struct in6_addr* ipad, mio_bch_t* buf,
break; break;
} }
/* TODO: tp += mio_fmt_uintmax_to_bcstr(tp, MIO_COUNTOF(tmp) - (tp - tmp), words[i], 16, 0, '\0', MIO_NULL); */ tp += mio_fmt_uintmax_to_bcstr(tp, MIO_COUNTOF(tmp) - (tp - tmp), words[i], 16, 0, '\0', MIO_NULL);
} }
/* Was it a trailing run of 0x00's? */ /* Was it a trailing run of 0x00's? */
@ -1231,7 +1232,7 @@ mio_oow_t mio_skadtobcstr (mio_t* mio, const mio_skad_t* _skad, mio_bch_t* buf,
} }
if (xlen + 1 >= len) goto done; if (xlen + 1 >= len) goto done;
/* xlen += mio_fmt_uintmax_to_bcstr(&buf[xlen], len - xlen, mio_ntoh16(skad->in4.sin_port), 10, 0, '\0', MIO_NULL);*/ xlen += mio_fmt_uintmax_to_bcstr(&buf[xlen], len - xlen, mio_ntoh16(skad->in4.sin_port), 10, 0, '\0', MIO_NULL);
} }
} }
break; break;
@ -1267,7 +1268,7 @@ mio_oow_t mio_skadtobcstr (mio_t* mio, const mio_skad_t* _skad, mio_bch_t* buf,
tmp = mio_ifindextobcstr(mio, skad->in6.sin6_scope_id, &buf[xlen], len - xlen); tmp = mio_ifindextobcstr(mio, skad->in6.sin6_scope_id, &buf[xlen], len - xlen);
if (tmp <= -1) if (tmp <= -1)
{ {
/* TODO xlen += mio_fmt_uintmax_to_bcstr(&buf[xlen], len - xlen, skad->in6.sin6_scope_id, 10, 0, '\0', MIO_NULL); */ xlen += mio_fmt_uintmax_to_bcstr(&buf[xlen], len - xlen, skad->in6.sin6_scope_id, 10, 0, '\0', MIO_NULL);
} }
else xlen += tmp; else xlen += tmp;
} }
@ -1287,7 +1288,7 @@ mio_oow_t mio_skadtobcstr (mio_t* mio, const mio_skad_t* _skad, mio_bch_t* buf,
} }
if (xlen + 1 >= len) goto done; if (xlen + 1 >= len) goto done;
/* xlen += mio_fmt_uintmax_to_bcstr(&buf[xlen], len - xlen, mio_ntoh16(skad->in6.sin6_port), 10, 0, '\0', MIO_NULL); */ xlen += mio_fmt_uintmax_to_bcstr(&buf[xlen], len - xlen, mio_ntoh16(skad->in6.sin6_port), 10, 0, '\0', MIO_NULL);
} }
} }
@ -1301,16 +1302,6 @@ mio_oow_t mio_skadtobcstr (mio_t* mio, const mio_skad_t* _skad, mio_bch_t* buf,
if (xlen + 1 >= len) goto done; if (xlen + 1 >= len) goto done;
xlen += mio_copy_bcstr(&buf[xlen], len - xlen, skad->un.sun_path); xlen += mio_copy_bcstr(&buf[xlen], len - xlen, skad->un.sun_path);
#if 0
if (xlen + 1 >= len) goto done;
else
{
mio_oow_t wcslen, mbslen = len - xlen;
mio_convutobcstr (mio, skad->un.sun_path, &wcslen, &buf[xlen], &mbslen);
/* i don't care about conversion errors */
xlen += mbslen;
}
#endif
} }
break; break;