added hio_dev_cap_to_bcstr() for easier debugging.

added hio_concat_uchars_to_ucstr()/hio_concat_bchars_to_bcstr()
added hio_concat_ucstr()/hio_concat_bcstr()
This commit is contained in:
hyung-hwan 2021-08-08 04:10:29 +00:00
parent 772d8237f0
commit e74a5554f2
8 changed files with 457 additions and 122 deletions

View File

@ -562,6 +562,12 @@ int main (int argc, char* argv[])
g_dev_type4 = HIO_DEV_SCK_SCTP4; g_dev_type4 = HIO_DEV_SCK_SCTP4;
g_dev_type6 = HIO_DEV_SCK_SCTP6; g_dev_type6 = HIO_DEV_SCK_SCTP6;
} }
else if (strcmp(argv[i], "-ss") == 0)
{
i++;
g_dev_type4 = HIO_DEV_SCK_SCTP4_SP;
g_dev_type6 = HIO_DEV_SCK_SCTP6_SP;
}
else if (strcmp(argv[i], "-t") == 0) else if (strcmp(argv[i], "-t") == 0)
{ {
i++; i++;

View File

@ -472,8 +472,8 @@ hio_dns_pkt_info_t* hio_dns_make_pkt_info (hio_t* hio, const hio_dns_pkt_t* pkt,
HIO_MEMSET (&pib, 0, HIO_SIZEOF(pib)); HIO_MEMSET (&pib, 0, HIO_SIZEOF(pib));
/* this is used a initial workspace and also indicates that it's the first run. /* pib is used as the initial workspace and also indicates that it's the first run.
* at the second run, it is set to a dynamically allocated memory block large enough * at the second run, pii is set to a dynamically allocated memory block large enough
* to hold actual data. */ * to hold actual data. */
pii = &pib; pii = &pib;

View File

@ -245,6 +245,14 @@ enum hio_trim_oochars_flag_t
extern "C" { extern "C" {
#endif #endif
HIO_EXPORT hio_oow_t hio_count_ucstr (
const hio_uch_t* str
);
HIO_EXPORT hio_oow_t hio_count_bcstr (
const hio_bch_t* str
);
/** /**
* The hio_equal_uchars() function determines equality of two strings * The hio_equal_uchars() function determines equality of two strings
* of the same length \a len. * of the same length \a len.
@ -408,6 +416,32 @@ HIO_EXPORT hio_oow_t hio_copy_bcstr_unlimited (
const hio_bch_t* src const hio_bch_t* src
); );
HIO_EXPORT hio_oow_t hio_concat_uchars_to_ucstr (
hio_uch_t* buf,
hio_oow_t bsz,
const hio_uch_t* src,
hio_oow_t len
);
HIO_EXPORT hio_oow_t hio_concat_bchars_to_bcstr (
hio_bch_t* buf,
hio_oow_t bsz,
const hio_bch_t* src,
hio_oow_t len
);
HIO_EXPORT hio_oow_t hio_concat_ucstr (
hio_uch_t* buf,
hio_oow_t bsz,
const hio_uch_t* src
);
HIO_EXPORT hio_oow_t hio_concat_bcstr (
hio_bch_t* buf,
hio_oow_t bsz,
const hio_bch_t* src
);
HIO_EXPORT void hio_fill_uchars ( HIO_EXPORT void hio_fill_uchars (
hio_uch_t* dst, hio_uch_t* dst,
const hio_uch_t ch, const hio_uch_t ch,
@ -496,15 +530,9 @@ HIO_EXPORT int hio_split_bcstr (
hio_bch_t escape hio_bch_t escape
); );
HIO_EXPORT hio_oow_t hio_count_ucstr (
const hio_uch_t* str
);
HIO_EXPORT hio_oow_t hio_count_bcstr (
const hio_bch_t* str
);
#if defined(HIO_OOCH_IS_UCH) #if defined(HIO_OOCH_IS_UCH)
# define hio_count_oocstr hio_count_ucstr
# define hio_equal_oochars hio_equal_uchars # define hio_equal_oochars hio_equal_uchars
# define hio_comp_oochars hio_comp_uchars # define hio_comp_oochars hio_comp_uchars
# define hio_comp_oocstr_bcstr hio_comp_ucstr_bcstr # define hio_comp_oocstr_bcstr hio_comp_ucstr_bcstr
@ -524,6 +552,9 @@ HIO_EXPORT hio_oow_t hio_count_bcstr (
# define hio_copy_oocstr hio_copy_ucstr # define hio_copy_oocstr hio_copy_ucstr
# define hio_copy_oocstr_unlimited hio_copy_ucstr_unlimited # define hio_copy_oocstr_unlimited hio_copy_ucstr_unlimited
# define hio_concat_oochars_to_ucstr hio_concat_uchars_to_ucstr
# define hio_concat_oocstr hio_concat_ucstr
# define hio_fill_oochars hio_fill_uchars # define hio_fill_oochars hio_fill_uchars
# define hio_find_oocstr_word_in_oocstr hio_find_ucstr_word_in_ucstr # define hio_find_oocstr_word_in_oocstr hio_find_ucstr_word_in_ucstr
# define hio_find_oochar hio_find_uchar # define hio_find_oochar hio_find_uchar
@ -532,8 +563,8 @@ HIO_EXPORT hio_oow_t hio_count_bcstr (
# define hio_trim_oochars hio_trim_uchars # define hio_trim_oochars hio_trim_uchars
# define hio_split_oocstr hio_split_ucstr # define hio_split_oocstr hio_split_ucstr
# define hio_count_oocstr hio_count_ucstr
#else #else
# define hio_count_oocstr hio_count_bcstr
# define hio_equal_oochars hio_equal_bchars # define hio_equal_oochars hio_equal_bchars
# define hio_comp_oochars hio_comp_bchars # define hio_comp_oochars hio_comp_bchars
# define hio_comp_oocstr_bcstr hio_comp_bcstr # define hio_comp_oocstr_bcstr hio_comp_bcstr
@ -553,6 +584,9 @@ HIO_EXPORT hio_oow_t hio_count_bcstr (
# define hio_copy_oocstr hio_copy_bcstr # define hio_copy_oocstr hio_copy_bcstr
# define hio_copy_oocstr_unlimited hio_copy_bcstr_unlimited # define hio_copy_oocstr_unlimited hio_copy_bcstr_unlimited
# define hio_concat_oochars_to_bcstr hio_concat_bchars_to_bcstr
# define hio_concat_oocstr hio_concat_bcstr
# define hio_fill_oochars hio_fill_bchars # define hio_fill_oochars hio_fill_bchars
# define hio_find_oocstr_word_in_oocstr hio_find_bcstr_word_in_bcstr # define hio_find_oocstr_word_in_oocstr hio_find_bcstr_word_in_bcstr
# define hio_find_oochar hio_find_bchar # define hio_find_oochar hio_find_bchar
@ -561,7 +595,6 @@ HIO_EXPORT hio_oow_t hio_count_bcstr (
# define hio_trim_oochars hio_trim_bchars # define hio_trim_oochars hio_trim_bchars
# define hio_split_oocstr hio_split_bcstr # define hio_split_oocstr hio_split_bcstr
# define hio_count_oocstr hio_count_bcstr
#endif #endif
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */

View File

@ -2195,3 +2195,37 @@ hio_oow_t hio_fmttobcstr (hio_t* hio, hio_bch_t* buf, hio_oow_t bufsz, const hio
} }
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
hio_oow_t hio_dev_cap_to_bcstr (hio_bitmask_t cap, hio_bch_t* buf, hio_oow_t size)
{
hio_oow_t len = 0;
if (size <= 0) return 0;
buf[len] = '\0';
if (cap & HIO_DEV_CAP_VIRTUAL) len += hio_copy_bcstr(&buf[len], size - len, "virtual|");
if (cap & HIO_DEV_CAP_IN) len += hio_copy_bcstr(&buf[len], size - len, "in|");
if (cap & HIO_DEV_CAP_OUT) len += hio_copy_bcstr(&buf[len], size - len, "out|");
if (cap & HIO_DEV_CAP_PRI) len += hio_copy_bcstr(&buf[len], size - len, "pri|");
if (cap & HIO_DEV_CAP_STREAM) len += hio_copy_bcstr(&buf[len], size - len, "stream|");
if (cap & HIO_DEV_CAP_IN_DISABLED) len += hio_copy_bcstr(&buf[len], size - len, "in_disabled|");
if (cap & HIO_DEV_CAP_OUT_UNQUEUEABLE) len += hio_copy_bcstr(&buf[len], size - len, "out_unqueueable|");
if (cap & HIO_DEV_CAP_IN_CLOSED) len += hio_copy_bcstr(&buf[len], size - len, "in_closed|");
if (cap & HIO_DEV_CAP_OUT_CLOSED) len += hio_copy_bcstr(&buf[len], size - len, "out_closed|");
if (cap & HIO_DEV_CAP_IN_WATCHED) len += hio_copy_bcstr(&buf[len], size - len, "in_watched|");
if (cap & HIO_DEV_CAP_OUT_WATCHED) len += hio_copy_bcstr(&buf[len], size - len, "out_watched|");
if (cap & HIO_DEV_CAP_PRI_WATCHED) len += hio_copy_bcstr(&buf[len], size - len, "pri_watched|");
if (cap & HIO_DEV_CAP_ACTIVE) len += hio_copy_bcstr(&buf[len], size - len, "active|");
if (cap & HIO_DEV_CAP_HALTED) len += hio_copy_bcstr(&buf[len], size - len, "halted|");
if (cap & HIO_DEV_CAP_ZOMBIE) len += hio_copy_bcstr(&buf[len], size - len, "zombie|");
if (cap & HIO_DEV_CAP_RENEW_REQUIRED) len += hio_copy_bcstr(&buf[len], size - len, "renew_required|");
if (cap & HIO_DEV_CAP_WATCH_STARTED) len += hio_copy_bcstr(&buf[len], size - len, "watch_started|");
if (cap & HIO_DEV_CAP_WATCH_SUSPENDED) len += hio_copy_bcstr(&buf[len], size - len, "watch_suspended|");
if (cap & HIO_DEV_CAP_WATCH_REREG_REQUIRED) len += hio_copy_bcstr(&buf[len], size - len, "watch_rereg_required|");
if (buf[len - 1] == '|') buf[--len] = '\0';
return len;
}

View File

@ -367,7 +367,7 @@ struct hio_wq_t
#define HIO_DEV_HEADER \ #define HIO_DEV_HEADER \
hio_t* hio; \ hio_t* hio; \
hio_oow_t dev_size; \ hio_oow_t dev_size; \
int dev_cap; \ hio_bitmask_t dev_cap; \
hio_dev_mth_t* dev_mth; \ hio_dev_mth_t* dev_mth; \
hio_dev_evcb_t* dev_evcb; \ hio_dev_evcb_t* dev_evcb; \
hio_ntime_t rtmout; \ hio_ntime_t rtmout; \
@ -409,31 +409,36 @@ struct hio_dev_t
enum hio_dev_cap_t enum hio_dev_cap_t
{ {
HIO_DEV_CAP_VIRTUAL = (1 << 0), /* don't forget to update hio_dev_cap_to_bcstr()
HIO_DEV_CAP_IN = (1 << 1), * when you add/delete these enumerators */
HIO_DEV_CAP_OUT = (1 << 2),
HIO_DEV_CAP_PRI = (1 << 3), /* meaningful only if #HIO_DEV_CAP_IN is set */ HIO_DEV_CAP_VIRTUAL = ((hio_bitmask_t)1 << 0),
HIO_DEV_CAP_STREAM = (1 << 4), HIO_DEV_CAP_IN = ((hio_bitmask_t)1 << 1),
HIO_DEV_CAP_IN_DISABLED = (1 << 5), HIO_DEV_CAP_OUT = ((hio_bitmask_t)1 << 2),
HIO_DEV_CAP_OUT_UNQUEUEABLE = (1 << 6), HIO_DEV_CAP_PRI = ((hio_bitmask_t)1 << 3), /* meaningful only if #HIO_DEV_CAP_IN is set */
HIO_DEV_CAP_STREAM = ((hio_bitmask_t)1 << 4), /* byte stream */
HIO_DEV_CAP_IN_DISABLED = ((hio_bitmask_t)1 << 5),
HIO_DEV_CAP_OUT_UNQUEUEABLE = ((hio_bitmask_t)1 << 6),
HIO_DEV_CAP_ALL_MASK = (HIO_DEV_CAP_VIRTUAL | HIO_DEV_CAP_IN | HIO_DEV_CAP_OUT | HIO_DEV_CAP_PRI | HIO_DEV_CAP_STREAM | HIO_DEV_CAP_IN_DISABLED | HIO_DEV_CAP_OUT_UNQUEUEABLE), HIO_DEV_CAP_ALL_MASK = (HIO_DEV_CAP_VIRTUAL | HIO_DEV_CAP_IN | HIO_DEV_CAP_OUT | HIO_DEV_CAP_PRI | HIO_DEV_CAP_STREAM | HIO_DEV_CAP_IN_DISABLED | HIO_DEV_CAP_OUT_UNQUEUEABLE),
/* ------------------------------------------------------------------- /* -------------------------------------------------------------------
* the followings bits are for internal use only. * the followings bits are for internal use only.
* never set these bits to the dev_cap field. * never set these bits to the dev_cap field.
* ------------------------------------------------------------------- */ * ------------------------------------------------------------------- */
HIO_DEV_CAP_IN_CLOSED = (1 << 10), HIO_DEV_CAP_IN_CLOSED = ((hio_bitmask_t)1 << 10),
HIO_DEV_CAP_OUT_CLOSED = (1 << 11), HIO_DEV_CAP_OUT_CLOSED = ((hio_bitmask_t)1 << 11),
HIO_DEV_CAP_IN_WATCHED = (1 << 12), HIO_DEV_CAP_IN_WATCHED = ((hio_bitmask_t)1 << 12),
HIO_DEV_CAP_OUT_WATCHED = (1 << 13), HIO_DEV_CAP_OUT_WATCHED = ((hio_bitmask_t)1 << 13),
HIO_DEV_CAP_PRI_WATCHED = (1 << 14), /**< can be set only if HIO_DEV_CAP_IN_WATCHED is set */ HIO_DEV_CAP_PRI_WATCHED = ((hio_bitmask_t)1 << 14), /**< can be set only if HIO_DEV_CAP_IN_WATCHED is set */
HIO_DEV_CAP_ACTIVE = (1 << 15), HIO_DEV_CAP_ACTIVE = ((hio_bitmask_t)1 << 15),
HIO_DEV_CAP_HALTED = (1 << 16), HIO_DEV_CAP_HALTED = ((hio_bitmask_t)1 << 16),
HIO_DEV_CAP_ZOMBIE = (1 << 17), HIO_DEV_CAP_ZOMBIE = ((hio_bitmask_t)1 << 17),
HIO_DEV_CAP_RENEW_REQUIRED = (1 << 18), HIO_DEV_CAP_RENEW_REQUIRED = ((hio_bitmask_t)1 << 18),
HIO_DEV_CAP_WATCH_STARTED = (1 << 19), HIO_DEV_CAP_WATCH_STARTED = ((hio_bitmask_t)1 << 19),
HIO_DEV_CAP_WATCH_SUSPENDED = (1 << 20), HIO_DEV_CAP_WATCH_SUSPENDED = ((hio_bitmask_t)1 << 20),
HIO_DEV_CAP_WATCH_REREG_REQUIRED = (1 << 21), HIO_DEV_CAP_WATCH_REREG_REQUIRED = ((hio_bitmask_t)1 << 21),
}; };
typedef enum hio_dev_cap_t hio_dev_cap_t; typedef enum hio_dev_cap_t hio_dev_cap_t;
@ -1412,6 +1417,12 @@ HIO_EXPORT const hio_ooch_t* hio_errnum_to_errstr (
hio_errnum_t errnum hio_errnum_t errnum
); );
HIO_EXPORT hio_oow_t hio_dev_cap_to_bcstr (
hio_bitmask_t cap,
hio_bch_t* buf,
hio_oow_t bsz
);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -39,6 +39,10 @@
#include <net/if.h> #include <net/if.h>
#include <netinet/if_ether.h> #include <netinet/if_ether.h>
#if defined(HAVE_NETINET_SCTP_H)
# include <netinet/sctp.h>
#endif
#if defined(HAVE_NETPACKET_PACKET_H) #if defined(HAVE_NETPACKET_PACKET_H)
# include <netpacket/packet.h> # include <netpacket/packet.h>
#endif #endif
@ -182,8 +186,8 @@ static hio_syshnd_t open_async_bpf (hio_t* hio)
if (fd == HIO_SYSHND_INVALID) goto oops; if (fd == HIO_SYSHND_INVALID) goto oops;
#if 0 #if 0
if (ioctl(fd, BIOCIMMEDIATE, &tmp) == -1) goto oops; if (ioctl(fd, BIOCIMMEDIATE, &tmp) <= -1) goto oops;
if (ioctl(fd, BIOCGBLEN, &bufsize) == -1) goto oops; if (ioctl(fd, BIOCGBLEN, &bufsize) <= -1) goto oops;
#endif #endif
return fd; return fd;
@ -221,7 +225,11 @@ struct sck_type_map_t
int domain; int domain;
int type; int type;
int proto; int proto;
int extra_dev_cap;
unsigned int connectable: 1;
unsigned int listenable: 1;
hio_bitmask_t extra_dev_cap;
}; };
#define __AF_BPF 999998 #define __AF_BPF 999998
@ -229,82 +237,82 @@ struct sck_type_map_t
static struct sck_type_map_t sck_type_map[] = static struct sck_type_map_t sck_type_map[] =
{ {
/* HIO_DEV_SCK_QX */ /* HIO_DEV_SCK_QX */
{ HIO_AF_QX, 0, 0, 0 }, { HIO_AF_QX, 0, 0, 0, 0, 0 },
#if defined(AF_UNIX) #if defined(AF_UNIX)
{ AF_UNIX, SOCK_STREAM, 0, HIO_DEV_CAP_STREAM }, { AF_UNIX, SOCK_STREAM, 0, 1, 1, HIO_DEV_CAP_STREAM },
#else #else
{ -1, 0, 0, 0 }, { -1, 0, 0, 0, 0, 0 },
#endif #endif
/* HIO_DEV_SCK_TCP4 */ /* HIO_DEV_SCK_TCP4 */
{ AF_INET, SOCK_STREAM, 0, HIO_DEV_CAP_STREAM }, { AF_INET, SOCK_STREAM, 0, 1, 1, HIO_DEV_CAP_STREAM },
/* HIO_DEV_SCK_TCP6 */ /* HIO_DEV_SCK_TCP6 */
{ AF_INET6, SOCK_STREAM, 0, HIO_DEV_CAP_STREAM }, { AF_INET6, SOCK_STREAM, 0, 1, 1, HIO_DEV_CAP_STREAM },
/* HIO_DEV_SCK_UPD4 */ /* HIO_DEV_SCK_UPD4 */ /* TODO: the socket api allows connect() on UDP sockets. should i mark it connectable? */
{ AF_INET, SOCK_DGRAM, 0, 0 }, { AF_INET, SOCK_DGRAM, 0, 0, 0, 0 },
/* HIO_DEV_SCK_UDP6 */ /* HIO_DEV_SCK_UDP6 */
{ AF_INET6, SOCK_DGRAM, 0, 0 }, { AF_INET6, SOCK_DGRAM, 0, 0, 0, 0 },
#if defined(IPPROTO_SCTP) #if defined(IPPROTO_SCTP)
/* HIO_DEV_SCK_SCTP4 */ /* HIO_DEV_SCK_SCTP4 */
{ AF_INET, SOCK_STREAM, IPPROTO_SCTP, HIO_DEV_CAP_STREAM }, { AF_INET, SOCK_STREAM, IPPROTO_SCTP, 1, 1, HIO_DEV_CAP_STREAM },
/* HIO_DEV_SCK_SCTP6 */ /* HIO_DEV_SCK_SCTP6 */
{ AF_INET6, SOCK_STREAM, IPPROTO_SCTP, HIO_DEV_CAP_STREAM }, { AF_INET6, SOCK_STREAM, IPPROTO_SCTP, 1, 1, HIO_DEV_CAP_STREAM },
/* HIO_DEV_SCK_SCTP4_SP - not implemented */ /* HIO_DEV_SCK_SCTP4_SP - not implemented */
{ -1, SOCK_SEQPACKET, IPPROTO_SCTP, 0 }, { AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP, 1, 1, 0 },
/* HIO_DEV_SCK_SCTP6_SP - not implemented */ /* HIO_DEV_SCK_SCTP6_SP - not implemented */
{ -1, SOCK_SEQPACKET, IPPROTO_SCTP, 0 }, { AF_INET6, SOCK_SEQPACKET, IPPROTO_SCTP, 1, 1, 0 },
#else #else
{ -1, 0, 0, 0 }, { -1, 0, 0, 0, 0, 0 },
{ -1, 0, 0, 0 }, { -1, 0, 0, 0, 0, 0 },
{ -1, 0, 0, 0 }, { -1, 0, 0, 0, 0, 0 },
{ -1, 0, 0, 0 }, { -1, 0, 0, 0, 0, 0 },
#endif #endif
/* HIO_DEV_SCK_ICMP4 - IP protocol field is 1 byte only. no byte order conversion is needed */ /* HIO_DEV_SCK_ICMP4 - IP protocol field is 1 byte only. no byte order conversion is needed */
{ AF_INET, SOCK_RAW, IPPROTO_ICMP, 0 }, { AF_INET, SOCK_RAW, IPPROTO_ICMP, 0, 0, 0 },
/* HIO_DEV_SCK_ICMP6 - IP protocol field is 1 byte only. no byte order conversion is needed */ /* HIO_DEV_SCK_ICMP6 - IP protocol field is 1 byte only. no byte order conversion is needed */
{ AF_INET6, SOCK_RAW, IPPROTO_ICMP, 0 }, { AF_INET6, SOCK_RAW, IPPROTO_ICMP, 0, 0, 0 },
#if defined(AF_PACKET) && (HIO_SIZEOF_STRUCT_SOCKADDR_LL > 0) #if defined(AF_PACKET) && (HIO_SIZEOF_STRUCT_SOCKADDR_LL > 0)
/* HIO_DEV_SCK_ARP - Ethernet type is 2 bytes long. Protocol must be specified in the network byte order */ /* HIO_DEV_SCK_ARP - Ethernet type is 2 bytes long. Protocol must be specified in the network byte order */
{ AF_PACKET, SOCK_RAW, HIO_CONST_HTON16(HIO_ETHHDR_PROTO_ARP), 0 }, { AF_PACKET, SOCK_RAW, HIO_CONST_HTON16(HIO_ETHHDR_PROTO_ARP), 0, 0, 0 },
/* HIO_DEV_SCK_ARP_DGRAM - link-level header removed*/ /* HIO_DEV_SCK_ARP_DGRAM - link-level header removed*/
{ AF_PACKET, SOCK_DGRAM, HIO_CONST_HTON16(HIO_ETHHDR_PROTO_ARP), 0 }, { AF_PACKET, SOCK_DGRAM, HIO_CONST_HTON16(HIO_ETHHDR_PROTO_ARP), 0, 0, 0 },
#elif defined(AF_LINK) && (HIO_SIZEOF_STRUCT_SOCKADDR_DL > 0) #elif defined(AF_LINK) && (HIO_SIZEOF_STRUCT_SOCKADDR_DL > 0)
/* HIO_DEV_SCK_ARP */ /* HIO_DEV_SCK_ARP */
{ AF_LINK, SOCK_RAW, HIO_CONST_HTON16(HIO_ETHHDR_PROTO_ARP), 0 }, { AF_LINK, SOCK_RAW, HIO_CONST_HTON16(HIO_ETHHDR_PROTO_ARP), 0, 0, 0 },
/* HIO_DEV_SCK_ARP_DGRAM */ /* HIO_DEV_SCK_ARP_DGRAM */
{ AF_LINK, SOCK_DGRAM, HIO_CONST_HTON16(HIO_ETHHDR_PROTO_ARP), 0 }, { AF_LINK, SOCK_DGRAM, HIO_CONST_HTON16(HIO_ETHHDR_PROTO_ARP), 0, 0, 0 },
#else #else
{ -1, 0, 0, 0 }, { -1, 0, 0, 0, 0, 0 },
{ -1, 0, 0, 0 }, { -1, 0, 0, 0, 0, 0 },
#endif #endif
#if defined(AF_PACKET) && (HIO_SIZEOF_STRUCT_SOCKADDR_LL > 0) #if defined(AF_PACKET) && (HIO_SIZEOF_STRUCT_SOCKADDR_LL > 0)
/* HIO_DEV_SCK_PACKET */ /* HIO_DEV_SCK_PACKET */
{ AF_PACKET, SOCK_RAW, HIO_CONST_HTON16(ETH_P_ALL), 0 }, { AF_PACKET, SOCK_RAW, HIO_CONST_HTON16(ETH_P_ALL), 0, 0, 0 },
#elif defined(AF_LINK) && (HIO_SIZEOF_STRUCT_SOCKADDR_DL > 0) #elif defined(AF_LINK) && (HIO_SIZEOF_STRUCT_SOCKADDR_DL > 0)
/* HIO_DEV_SCK_PACKET */ /* HIO_DEV_SCK_PACKET */
{ AF_LINK, SOCK_RAW, HIO_CONST_HTON16(0), 0 }, { AF_LINK, SOCK_RAW, HIO_CONST_HTON16(0), 0, 0, 0 },
#else #else
{ -1, 0, 0, 0 }, { -1, 0, 0, 0, 0, 0 },
#endif #endif
/* HIO_DEV_SCK_BPF - arp */ /* HIO_DEV_SCK_BPF - arp */
{ __AF_BPF, 0, 0, 0 } /* not implemented yet */ { __AF_BPF, 0, 0, 0, 0, 0 } /* not implemented yet */
}; };
/* ======================================================================== */ /* ======================================================================== */
@ -430,6 +438,18 @@ static int dev_sck_make (hio_dev_t* dev, void* ctx)
{ {
hnd = open_async_socket(hio, sck_type_map[arg->type].domain, sck_type_map[arg->type].type, sck_type_map[arg->type].proto); hnd = open_async_socket(hio, sck_type_map[arg->type].domain, sck_type_map[arg->type].type, sck_type_map[arg->type].proto);
if (hnd == HIO_SYSHND_INVALID) goto oops; if (hnd == HIO_SYSHND_INVALID) goto oops;
#if defined(IPPROTO_SCTP)
if (sck_type_map[arg->type].type == SOCK_SEQPACKET &&
sck_type_map[arg->type].proto == IPPROTO_SCTP)
{
struct sctp_event_subscribe sctp_ev_s;
HIO_MEMSET (&sctp_ev_s, 0, HIO_SIZEOF(sctp_ev_s));
sctp_ev_s.sctp_data_io_event = 1;
setsockopt (hnd, IPPROTO_SCTP, SCTP_EVENTS, &sctp_ev_s, HIO_SIZEOF(sctp_ev_s));
}
#endif
} }
rdev->hnd = hnd; rdev->hnd = hnd;
@ -585,7 +605,7 @@ static int dev_sck_read_stateful (hio_dev_t* dev, void* buf, hio_iolen_t* len, h
ssize_t x; ssize_t x;
x = recv(rdev->hnd, buf, *len, 0); x = recv(rdev->hnd, buf, *len, 0);
if (x == -1) if (x <= -1)
{ {
if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) return 0; /* no data available */ if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) return 0; /* no data available */
if (errno == EINTR) return 0; if (errno == EINTR) return 0;
@ -636,6 +656,54 @@ static int dev_sck_read_bpf (hio_dev_t* dev, void* buf, hio_iolen_t* len, hio_de
return -1; return -1;
} }
#if defined(IPPROTO_SCTP)
static int dev_sck_read_sctp_sp (hio_dev_t* dev, void* buf, hio_iolen_t* len, hio_devaddr_t* srcaddr)
{
hio_t* hio = dev->hio;
hio_dev_sck_t* rdev = (hio_dev_sck_t*)dev;
hio_scklen_t srcaddrlen;
ssize_t x;
int msg_flags;
struct sctp_sndrcvinfo sri;
srcaddrlen = HIO_SIZEOF(rdev->remoteaddr);
/*
struct sctp_sndrcvinfo {
__u16 sinfo_stream;
__u16 sinfo_ssn;
__u16 sinfo_flags;
__u32 sinfo_ppid;
__u32 sinfo_context;
__u32 sinfo_timetolive;
__u32 sinfo_tsn;
__u32 sinfo_cumtsn;
sctp_assoc_t sinfo_assoc_id;
};
*/
/* msg_flags -> flags such as MSG_NOTIFICATION or MSG_EOR */
x = sctp_recvmsg(rdev->hnd, buf, *len, (struct sockaddr*)&rdev->remoteaddr, &srcaddrlen, &sri, &msg_flags);
if (x <= -1)
{
int eno = errno;
if (eno == EINPROGRESS || eno == EWOULDBLOCK || eno == EAGAIN) return 0; /* no data available */
if (eno == EINTR) return 0;
hio_seterrwithsyserr (hio, 0, eno);
HIO_DEBUG2 (hio, "SCK(%p) - recvfrom failure - %hs", rdev, strerror(eno));
return -1;
}
srcaddr->ptr = &rdev->remoteaddr;
srcaddr->len = srcaddrlen;
*len = x;
//*sid = sri.sinfo_stream; /* stream number */
return 1;
}
#endif
/* ------------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------------ */
static int dev_sck_write_stateful (hio_dev_t* dev, const void* data, hio_iolen_t* len, const hio_devaddr_t* dstaddr) static int dev_sck_write_stateful (hio_dev_t* dev, const void* data, hio_iolen_t* len, const hio_devaddr_t* dstaddr)
@ -652,7 +720,7 @@ static int dev_sck_write_stateful (hio_dev_t* dev, const void* data, hio_iolen_t
{ {
/* it's a writing finish indicator. close the writing end of /* it's a writing finish indicator. close the writing end of
* the socket, probably leaving it in the half-closed state */ * the socket, probably leaving it in the half-closed state */
if ((x = SSL_shutdown((SSL*)rdev->ssl)) == -1) if ((x = SSL_shutdown((SSL*)rdev->ssl)) <= -1)
{ {
set_ssl_error (hio, SSL_get_error((SSL*)rdev->ssl, x)); set_ssl_error (hio, SSL_get_error((SSL*)rdev->ssl, x));
return -1; return -1;
@ -682,7 +750,7 @@ static int dev_sck_write_stateful (hio_dev_t* dev, const void* data, hio_iolen_t
/* the write handler for a stream device must handle a zero-length /* the write handler for a stream device must handle a zero-length
* writing request specially. it's a writing finish indicator. close * writing request specially. it's a writing finish indicator. close
* the writing end of the socket, probably leaving it in the half-closed state */ * the writing end of the socket, probably leaving it in the half-closed state */
if (shutdown(rdev->hnd, SHUT_WR) == -1) if (shutdown(rdev->hnd, SHUT_WR) <= -1)
{ {
hio_seterrwithsyserr (hio, 0, errno); hio_seterrwithsyserr (hio, 0, errno);
return -1; return -1;
@ -698,7 +766,7 @@ static int dev_sck_write_stateful (hio_dev_t* dev, const void* data, hio_iolen_t
flags |= MSG_NOSIGNAL; flags |= MSG_NOSIGNAL;
#endif #endif
x = send(rdev->hnd, data, *len, flags); x = send(rdev->hnd, data, *len, flags);
if (x == -1) if (x <= -1)
{ {
if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) return 0; /* no data can be written */ if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) return 0; /* no data can be written */
if (errno == EINTR) return 0; if (errno == EINTR) return 0;
@ -729,7 +797,7 @@ static int dev_sck_writev_stateful (hio_dev_t* dev, const hio_iovec_t* iov, hio_
{ {
/* it's a writing finish indicator. close the writing end of /* it's a writing finish indicator. close the writing end of
* the socket, probably leaving it in the half-closed state */ * the socket, probably leaving it in the half-closed state */
if ((x = SSL_shutdown((SSL*)rdev->ssl)) == -1) if ((x = SSL_shutdown((SSL*)rdev->ssl)) <= -1)
{ {
set_ssl_error (hio, SSL_get_error((SSL*)rdev->ssl, x)); set_ssl_error (hio, SSL_get_error((SSL*)rdev->ssl, x));
return -1; return -1;
@ -767,7 +835,7 @@ static int dev_sck_writev_stateful (hio_dev_t* dev, const hio_iovec_t* iov, hio_
{ {
/* it's a writing finish indicator. close the writing end of /* it's a writing finish indicator. close the writing end of
* the socket, probably leaving it in the half-closed state */ * the socket, probably leaving it in the half-closed state */
if (shutdown(rdev->hnd, SHUT_WR) == -1) if (shutdown(rdev->hnd, SHUT_WR) <= -1)
{ {
hio_seterrwithsyserr (hio, 0, errno); hio_seterrwithsyserr (hio, 0, errno);
return -1; return -1;
@ -792,7 +860,7 @@ static int dev_sck_writev_stateful (hio_dev_t* dev, const hio_iovec_t* iov, hio_
#else #else
x = writev(rdev->hnd, (const struct iovec*)iov, *iovcnt); x = writev(rdev->hnd, (const struct iovec*)iov, *iovcnt);
#endif #endif
if (x == -1) if (x <= -1)
{ {
if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) return 0; /* no data can be written */ if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) return 0; /* no data can be written */
if (errno == EINTR) return 0; if (errno == EINTR) return 0;
@ -883,6 +951,42 @@ static int dev_sck_writev_bpf (hio_dev_t* dev, const hio_iovec_t* iov, hio_iolen
return -1; return -1;
} }
/* ------------------------------------------------------------------------------ */
#if defined(IPPROTO_SCTPXX)
static int dev_sck_write_sctp_sp (hio_dev_t* dev, const void* data, hio_iolen_t* len, const hio_devaddr_t* dstaddr)
{
hio_t* hio = dev->hio;
hio_dev_sck_t* rdev = (hio_dev_sck_t*)dev;
ssize_t x;
x = sctp_sendmsg(rdev->hnd,
data, *len, dstaddr->ptr, dstaddr->len,
sir->info_ppid, /* ppid - opaque */
0, /* flags (e.g. SCTP_UNORDERED, SCTP_EOF, SCT_ABORT, ...) */,
sid, /* stream number */
0, /* ttl */
0 /* context*/);
if (x <= -1)
{
if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) return 0; /* no data can be written */
if (errno == EINTR) return 0;
hio_seterrwithsyserr (hio, 0, errno);
return -1;
}
*len = x;
return 1;
}
static int dev_sck_writev_sctp_sp (hio_dev_t* dev, const hio_iovec_t* iov, hio_iolen_t* iovcnt, const hio_devaddr_t* dstaddr)
{
/* TODO: use sctp_sendv? */
hio_t* hio = dev->hio;
hio_dev_sck_t* rdev = (hio_dev_sck_t*)dev;
hio_seterrwithsyserr (hio, 0, HIO_ENOIMPL);
return -1;
}
#endif
/* ------------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------------ */
@ -901,7 +1005,7 @@ static int dev_sck_sendfile_stateful (hio_dev_t* dev, hio_syshnd_t in_fd, hio_fo
{ {
/* it's a writing finish indicator. close the writing end of /* it's a writing finish indicator. close the writing end of
* the socket, probably leaving it in the half-closed state */ * the socket, probably leaving it in the half-closed state */
if ((x = SSL_shutdown((SSL*)rdev->ssl)) == -1) if ((x = SSL_shutdown((SSL*)rdev->ssl)) <= -1)
{ {
set_ssl_error (hio, SSL_get_error((SSL*)rdev->ssl, x)); set_ssl_error (hio, SSL_get_error((SSL*)rdev->ssl, x));
return -1; return -1;
@ -930,7 +1034,7 @@ static int dev_sck_sendfile_stateful (hio_dev_t* dev, hio_syshnd_t in_fd, hio_fo
/* the write handler for a stream device must handle a zero-length /* the write handler for a stream device must handle a zero-length
* writing request specially. it's a writing finish indicator. close * writing request specially. it's a writing finish indicator. close
* the writing end of the socket, probably leaving it in the half-closed state */ * the writing end of the socket, probably leaving it in the half-closed state */
if (shutdown(rdev->hnd, SHUT_WR) == -1) if (shutdown(rdev->hnd, SHUT_WR) <= -1)
{ {
hio_seterrwithsyserr (hio, 0, errno); hio_seterrwithsyserr (hio, 0, errno);
return -1; return -1;
@ -944,7 +1048,7 @@ static int dev_sck_sendfile_stateful (hio_dev_t* dev, hio_syshnd_t in_fd, hio_fo
#if defined(HAVE_SENDFILE) #if defined(HAVE_SENDFILE)
/* TODO: cater for other systems */ /* TODO: cater for other systems */
x = sendfile(rdev->hnd, in_fd, &foff, *len); x = sendfile(rdev->hnd, in_fd, &foff, *len);
if (x == -1) if (x <= -1)
{ {
if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) return 0; /* no data can be written */ if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) return 0; /* no data can be written */
if (errno == EINTR) return 0; if (errno == EINTR) return 0;
@ -1072,7 +1176,7 @@ static int dev_sck_ioctl (hio_dev_t* dev, int cmd, void* arg)
{ {
/* TODO: should i make it into bnd->options? HIO_DEV_SCK_BIND_IPV6ONLY? applicable to ipv6 though. */ /* TODO: should i make it into bnd->options? HIO_DEV_SCK_BIND_IPV6ONLY? applicable to ipv6 though. */
int v = 1; int v = 1;
if (setsockopt(rdev->hnd, IPPROTO_IPV6, IPV6_V6ONLY, &v, HIO_SIZEOF(v)) == -1) if (setsockopt(rdev->hnd, IPPROTO_IPV6, IPV6_V6ONLY, &v, HIO_SIZEOF(v)) <= -1)
{ {
if (!(bnd->options & HIO_DEV_SCK_BIND_IGNERR)) if (!(bnd->options & HIO_DEV_SCK_BIND_IGNERR))
{ {
@ -1085,7 +1189,7 @@ static int dev_sck_ioctl (hio_dev_t* dev, int cmd, void* arg)
if (bnd->options & HIO_DEV_SCK_BIND_BROADCAST) if (bnd->options & HIO_DEV_SCK_BIND_BROADCAST)
{ {
int v = 1; int v = 1;
if (setsockopt(rdev->hnd, SOL_SOCKET, SO_BROADCAST, &v, HIO_SIZEOF(v)) == -1) if (setsockopt(rdev->hnd, SOL_SOCKET, SO_BROADCAST, &v, HIO_SIZEOF(v)) <= -1)
{ {
/* not affected by HIO_DEV_SCK_BIND_IGNERR */ /* not affected by HIO_DEV_SCK_BIND_IGNERR */
hio_seterrbfmtwithsyserr (hio, 0, errno, "unable to set SO_BROADCAST"); hio_seterrbfmtwithsyserr (hio, 0, errno, "unable to set SO_BROADCAST");
@ -1097,7 +1201,7 @@ static int dev_sck_ioctl (hio_dev_t* dev, int cmd, void* arg)
{ {
#if defined(SO_REUSEADDR) #if defined(SO_REUSEADDR)
int v = 1; int v = 1;
if (setsockopt(rdev->hnd, SOL_SOCKET, SO_REUSEADDR, &v, HIO_SIZEOF(v)) == -1) if (setsockopt(rdev->hnd, SOL_SOCKET, SO_REUSEADDR, &v, HIO_SIZEOF(v)) <= -1)
{ {
if (!(bnd->options & HIO_DEV_SCK_BIND_IGNERR)) if (!(bnd->options & HIO_DEV_SCK_BIND_IGNERR))
{ {
@ -1117,7 +1221,7 @@ static int dev_sck_ioctl (hio_dev_t* dev, int cmd, void* arg)
{ {
#if defined(SO_REUSEPORT) #if defined(SO_REUSEPORT)
int v = 1; int v = 1;
if (setsockopt(rdev->hnd, SOL_SOCKET, SO_REUSEPORT, &v, HIO_SIZEOF(v)) == -1) if (setsockopt(rdev->hnd, SOL_SOCKET, SO_REUSEPORT, &v, HIO_SIZEOF(v)) <= -1)
{ {
if (!(bnd->options & HIO_DEV_SCK_BIND_IGNERR)) if (!(bnd->options & HIO_DEV_SCK_BIND_IGNERR))
{ {
@ -1137,7 +1241,7 @@ static int dev_sck_ioctl (hio_dev_t* dev, int cmd, void* arg)
{ {
#if defined(IP_TRANSPARENT) #if defined(IP_TRANSPARENT)
int v = 1; int v = 1;
if (setsockopt(rdev->hnd, SOL_IP, IP_TRANSPARENT, &v, HIO_SIZEOF(v)) == -1) if (setsockopt(rdev->hnd, SOL_IP, IP_TRANSPARENT, &v, HIO_SIZEOF(v)) <= -1)
{ {
hio_seterrbfmtwithsyserr (hio, 0, errno, "unable to set IP_TRANSPARENT"); hio_seterrbfmtwithsyserr (hio, 0, errno, "unable to set IP_TRANSPARENT");
return -1; return -1;
@ -1205,7 +1309,7 @@ static int dev_sck_ioctl (hio_dev_t* dev, int cmd, void* arg)
} }
x = bind(rdev->hnd, (struct sockaddr*)&bnd->localaddr, hio_skad_size(&bnd->localaddr)); x = bind(rdev->hnd, (struct sockaddr*)&bnd->localaddr, hio_skad_size(&bnd->localaddr));
if (x == -1) if (x <= -1)
{ {
hio_seterrwithsyserr (hio, 0, errno); hio_seterrwithsyserr (hio, 0, errno);
#if defined(USE_SSL) #if defined(USE_SSL)
@ -1240,7 +1344,7 @@ static int dev_sck_ioctl (hio_dev_t* dev, int cmd, void* arg)
return -1; return -1;
} }
if (!IS_STATEFUL(rdev)) if (!sck_type_map[rdev->type].connectable)
{ {
hio_seterrbfmt (hio, HIO_EPERM, "disallowed to connect stateless device"); hio_seterrbfmt (hio, HIO_EPERM, "disallowed to connect stateless device");
return -1; return -1;
@ -1381,14 +1485,14 @@ fcntl (rdev->hnd, F_SETFL, flags | O_NONBLOCK);
return -1; return -1;
} }
if (!IS_STATEFUL(rdev)) if (!sck_type_map[rdev->type].listenable)
{ {
hio_seterrbfmt (hio, HIO_EPERM, "disallowed to listen on stateless device"); hio_seterrbfmt (hio, HIO_EPERM, "disallowed to listen on stateless device");
return -1; return -1;
} }
x = listen(rdev->hnd, lstn->backlogs); x = listen(rdev->hnd, lstn->backlogs);
if (x == -1) if (x <= -1)
{ {
hio_seterrwithsyserr (hio, 0, errno); hio_seterrwithsyserr (hio, 0, errno);
return -1; return -1;
@ -1492,7 +1596,7 @@ static int harvest_outgoing_connection (hio_dev_sck_t* rdev)
HIO_ASSERT (hio, !(rdev->state & HIO_DEV_SCK_CONNECTED)); HIO_ASSERT (hio, !(rdev->state & HIO_DEV_SCK_CONNECTED));
len = HIO_SIZEOF(errcode); len = HIO_SIZEOF(errcode);
if (getsockopt(rdev->hnd, SOL_SOCKET, SO_ERROR, (char*)&errcode, &len) == -1) if (getsockopt(rdev->hnd, SOL_SOCKET, SO_ERROR, (char*)&errcode, &len) <= -1)
{ {
hio_seterrbfmtwithsyserr (hio, 0, errno, "unable to get SO_ERROR"); hio_seterrbfmtwithsyserr (hio, 0, errno, "unable to get SO_ERROR");
return -1; return -1;
@ -1606,11 +1710,11 @@ static int make_accepted_client_connection (hio_dev_sck_t* rdev, hio_syshnd_t cl
clidev->type = clisck_type; clidev->type = clisck_type;
HIO_ASSERT (hio, clidev->hnd == clisck); HIO_ASSERT (hio, clidev->hnd == clisck);
clidev->dev_cap |= HIO_DEV_CAP_IN | HIO_DEV_CAP_OUT | HIO_DEV_CAP_STREAM; clidev->dev_cap |= HIO_DEV_CAP_IN | HIO_DEV_CAP_OUT | sck_type_map[clisck_type].extra_dev_cap;
clidev->remoteaddr = *remoteaddr; clidev->remoteaddr = *remoteaddr;
addrlen = HIO_SIZEOF(clidev->localaddr); addrlen = HIO_SIZEOF(clidev->localaddr);
if (getsockname(clisck, (struct sockaddr*)&clidev->localaddr, &addrlen) == -1) clidev->localaddr = rdev->localaddr; if (getsockname(clisck, (struct sockaddr*)&clidev->localaddr, &addrlen) <= -1) clidev->localaddr = rdev->localaddr;
#if defined(SO_ORIGINAL_DST) #if defined(SO_ORIGINAL_DST)
/* if REDIRECT is used, SO_ORIGINAL_DST returns the original /* if REDIRECT is used, SO_ORIGINAL_DST returns the original
@ -1618,7 +1722,7 @@ static int make_accepted_client_connection (hio_dev_sck_t* rdev, hio_syshnd_t cl
* the address of the local socket. In this case, it should * the address of the local socket. In this case, it should
* be same as the result of getsockname(). */ * be same as the result of getsockname(). */
addrlen = HIO_SIZEOF(clidev->orgdstaddr); addrlen = HIO_SIZEOF(clidev->orgdstaddr);
if (getsockopt(clisck, SOL_IP, SO_ORIGINAL_DST, &clidev->orgdstaddr, &addrlen) == -1) clidev->orgdstaddr = rdev->localaddr; if (getsockopt(clisck, SOL_IP, SO_ORIGINAL_DST, &clidev->orgdstaddr, &addrlen) <= -1) clidev->orgdstaddr = rdev->localaddr;
#else #else
clidev->orgdstaddr = rdev->localaddr; clidev->orgdstaddr = rdev->localaddr;
#endif #endif
@ -1761,7 +1865,7 @@ static int dev_evcb_sck_ready_stateful (hio_dev_t* dev, int events)
hio_scklen_t len; hio_scklen_t len;
len = HIO_SIZEOF(errcode); len = HIO_SIZEOF(errcode);
if (getsockopt(rdev->hnd, SOL_SOCKET, SO_ERROR, (char*)&errcode, &len) == -1) if (getsockopt(rdev->hnd, SOL_SOCKET, SO_ERROR, (char*)&errcode, &len) <= -1)
{ {
/* the error number is set to the socket error code. /* the error number is set to the socket error code.
* errno resulting from getsockopt() doesn't reflect the actual * errno resulting from getsockopt() doesn't reflect the actual
@ -1945,7 +2049,7 @@ static int dev_evcb_sck_ready_stateless (hio_dev_t* dev, int events)
hio_scklen_t len; hio_scklen_t len;
len = HIO_SIZEOF(errcode); len = HIO_SIZEOF(errcode);
if (getsockopt(rdev->hnd, SOL_SOCKET, SO_ERROR, (char*)&errcode, &len) == -1) if (getsockopt(rdev->hnd, SOL_SOCKET, SO_ERROR, (char*)&errcode, &len) <= -1)
{ {
/* the error number is set to the socket error code. /* the error number is set to the socket error code.
* errno resulting from getsockopt() doesn't reflect the actual * errno resulting from getsockopt() doesn't reflect the actual
@ -2020,7 +2124,7 @@ static int dev_evcb_sck_ready_qx (hio_dev_t* dev, int events)
hio_scklen_t len; hio_scklen_t len;
len = HIO_SIZEOF(errcode); len = HIO_SIZEOF(errcode);
if (getsockopt(rdev->hnd, SOL_SOCKET, SO_ERROR, (char*)&errcode, &len) == -1) if (getsockopt(rdev->hnd, SOL_SOCKET, SO_ERROR, (char*)&errcode, &len) <= -1)
{ {
/* the error number is set to the socket error code. /* the error number is set to the socket error code.
* errno resulting from getsockopt() doesn't reflect the actual * errno resulting from getsockopt() doesn't reflect the actual

View File

@ -38,6 +38,24 @@
hio_oow_t hio_count_ucstr (const hio_uch_t* str)
{
const hio_uch_t* ptr = str;
while (*ptr != '\0') ptr++;
return ptr - str;
}
hio_oow_t hio_count_bcstr (const hio_bch_t* str)
{
const hio_bch_t* ptr = str;
while (*ptr != '\0') ptr++;
return ptr - str;
}
int hio_equal_uchars (const hio_uch_t* str1, const hio_uch_t* str2, hio_oow_t len) int hio_equal_uchars (const hio_uch_t* str1, const hio_uch_t* str2, hio_oow_t len)
{ {
hio_oow_t i; hio_oow_t i;
@ -208,6 +226,101 @@ int hio_comp_bcstr (const hio_bch_t* str1, const hio_bch_t* str2, int ignorecase
hio_oow_t hio_concat_uchars_to_ucstr (hio_uch_t* buf, hio_oow_t bsz, const hio_uch_t* str, hio_oow_t len)
{
hio_uch_t* p, * p2;
const hio_uch_t* end;
hio_oow_t blen;
blen = hio_count_ucstr(buf);
if (blen >= bsz) return blen; /* something wrong */
p = buf + blen;
p2 = buf + bsz - 1;
end = str + len;
while (p < p2)
{
if (str >= end) break;
*p++ = *str++;
}
if (bsz > 0) *p = '\0';
return p - buf;
}
hio_oow_t hio_concat_bchars_to_bcstr (hio_bch_t* buf, hio_oow_t bsz, const hio_bch_t* str, hio_oow_t len)
{
hio_bch_t* p, * p2;
const hio_bch_t* end;
hio_oow_t blen;
blen = hio_count_bcstr(buf);
if (blen >= bsz) return blen; /* something wrong */
p = buf + blen;
p2 = buf + bsz - 1;
end = str + len;
while (p < p2)
{
if (str >= end) break;
*p++ = *str++;
}
if (bsz > 0) *p = '\0';
return p - buf;
}
hio_oow_t hio_concat_ucstr (hio_uch_t* buf, hio_oow_t bsz, const hio_uch_t* str)
{
hio_uch_t* p, * p2;
hio_oow_t blen;
blen = hio_count_ucstr(buf);
if (blen >= bsz) return blen; /* something wrong */
p = buf + blen;
p2 = buf + bsz - 1;
while (p < p2)
{
if (*str == '\0') break;
*p++ = *str++;
}
if (bsz > 0) *p = '\0';
return p - buf;
}
hio_oow_t hio_concat_bcstr (hio_bch_t* buf, hio_oow_t bsz, const hio_bch_t* str)
{
hio_bch_t* p, * p2;
hio_oow_t blen;
blen = hio_count_bcstr(buf);
if (blen >= bsz) return blen; /* something wrong */
p = buf + blen;
p2 = buf + bsz - 1;
while (p < p2)
{
if (*str == '\0') break;
*p++ = *str++;
}
if (bsz > 0) *p = '\0';
return p - buf;
}
void hio_fill_uchars (hio_uch_t* dst, hio_uch_t ch, hio_oow_t len) void hio_fill_uchars (hio_uch_t* dst, hio_uch_t ch, hio_oow_t len)
{ {
@ -225,24 +338,6 @@ void hio_fill_bchars (hio_bch_t* dst, hio_bch_t ch, hio_oow_t len)
hio_oow_t hio_count_ucstr (const hio_uch_t* str)
{
const hio_uch_t* ptr = str;
while (*ptr != '\0') ptr++;
return ptr - str;
}
hio_oow_t hio_count_bcstr (const hio_bch_t* str)
{
const hio_bch_t* ptr = str;
while (*ptr != '\0') ptr++;
return ptr - str;
}
hio_uch_t* hio_find_uchar (const hio_uch_t* ptr, hio_oow_t len, hio_uch_t c) hio_uch_t* hio_find_uchar (const hio_uch_t* ptr, hio_oow_t len, hio_uch_t c)
{ {
const hio_uch_t* end; const hio_uch_t* end;
@ -904,8 +999,6 @@ exit_point:
hio_intmax_t hio_uchars_to_intmax (const hio_uch_t* str, hio_oow_t len, int option, const hio_uch_t** endptr, int* is_sober) hio_intmax_t hio_uchars_to_intmax (const hio_uch_t* str, hio_oow_t len, int option, const hio_uch_t** endptr, int* is_sober)
{ {
hio_intmax_t n = 0; hio_intmax_t n = 0;

View File

@ -37,6 +37,18 @@
dnl --------------------------------------------------------------------------- dnl ---------------------------------------------------------------------------
changequote(`[[', `]]') changequote(`[[', `]]')
dnl ---------------------------------------------------------------------------
define([[fn_count_cstr]], [[ define([[fn_name]], $1) define([[char_type]], $2)
hio_oow_t fn_name (const char_type* str)
{
const char_type* ptr = str;
while (*ptr != '\0') ptr++;
return ptr - str;
}
]])
fn_count_cstr(hio_count_ucstr, hio_uch_t)
fn_count_cstr(hio_count_bcstr, hio_bch_t)
dnl --------------------------------------------------------------------------- dnl ---------------------------------------------------------------------------
define([[fn_equal_chars]], [[ define([[fn_name]], $1) define([[char_type]], $2) define([[fn_equal_chars]], [[ define([[fn_name]], $1) define([[char_type]], $2)
int fn_name (const char_type* str1, const char_type* str2, hio_oow_t len) int fn_name (const char_type* str1, const char_type* str2, hio_oow_t len)
@ -132,6 +144,62 @@ int fn_name (const char_type* str1, const char_type* str2, int ignorecase)
fn_comp_cstr(hio_comp_ucstr, hio_uch_t, hio_uchu_t, hio_to_uch_lower) fn_comp_cstr(hio_comp_ucstr, hio_uch_t, hio_uchu_t, hio_to_uch_lower)
fn_comp_cstr(hio_comp_bcstr, hio_bch_t, hio_bchu_t, hio_to_bch_lower) fn_comp_cstr(hio_comp_bcstr, hio_bch_t, hio_bchu_t, hio_to_bch_lower)
dnl ---------------------------------------------------------------------------
define([[fn_concat_chars_to_cstr]], [[ define([[fn_name]], $1) define([[char_type]], $2) dnl: $3 count_str
hio_oow_t fn_name (char_type* buf, hio_oow_t bsz, const char_type* str, hio_oow_t len)
{
char_type* p, * p2;
const char_type* end;
hio_oow_t blen;
blen = $3(buf);
if (blen >= bsz) return blen; /* something wrong */
p = buf + blen;
p2 = buf + bsz - 1;
end = str + len;
while (p < p2)
{
if (str >= end) break;
*p++ = *str++;
}
if (bsz > 0) *p = '\0';
return p - buf;
}
]])
fn_concat_chars_to_cstr(hio_concat_uchars_to_ucstr, hio_uch_t, hio_count_ucstr)
fn_concat_chars_to_cstr(hio_concat_bchars_to_bcstr, hio_bch_t, hio_count_bcstr)
dnl ---------------------------------------------------------------------------
define([[fn_concat_cstr]], [[ define([[fn_name]], $1) define([[char_type]], $2) dnl: $3 count_str
hio_oow_t fn_name (char_type* buf, hio_oow_t bsz, const char_type* str)
{
char_type* p, * p2;
hio_oow_t blen;
blen = $3(buf);
if (blen >= bsz) return blen; /* something wrong */
p = buf + blen;
p2 = buf + bsz - 1;
while (p < p2)
{
if (*str == '\0') break;
*p++ = *str++;
}
if (bsz > 0) *p = '\0';
return p - buf;
}
]])
fn_concat_cstr(hio_concat_ucstr, hio_uch_t, hio_count_ucstr)
fn_concat_cstr(hio_concat_bcstr, hio_bch_t, hio_count_bcstr)
dnl --------------------------------------------------------------------------- dnl ---------------------------------------------------------------------------
define([[fn_fill_chars]], [[ define([[fn_name]], $1) define([[char_type]], $2) define([[fn_fill_chars]], [[ define([[fn_name]], $1) define([[char_type]], $2)
void fn_name (char_type* dst, char_type ch, hio_oow_t len) void fn_name (char_type* dst, char_type ch, hio_oow_t len)
@ -143,18 +211,6 @@ void fn_name (char_type* dst, char_type ch, hio_oow_t len)
fn_fill_chars(hio_fill_uchars, hio_uch_t) fn_fill_chars(hio_fill_uchars, hio_uch_t)
fn_fill_chars(hio_fill_bchars, hio_bch_t) fn_fill_chars(hio_fill_bchars, hio_bch_t)
dnl ---------------------------------------------------------------------------
define([[fn_count_cstr]], [[ define([[fn_name]], $1) define([[char_type]], $2)
hio_oow_t fn_name (const char_type* str)
{
const char_type* ptr = str;
while (*ptr != '\0') ptr++;
return ptr - str;
}
]])
fn_count_cstr(hio_count_ucstr, hio_uch_t)
fn_count_cstr(hio_count_bcstr, hio_bch_t)
dnl --------------------------------------------------------------------------- dnl ---------------------------------------------------------------------------
define([[fn_find_char]], [[ define([[fn_name]], $1) define([[char_type]], $2) define([[fn_find_char]], [[ define([[fn_name]], $1) define([[char_type]], $2)
char_type* fn_name (const char_type* ptr, hio_oow_t len, char_type c) char_type* fn_name (const char_type* ptr, hio_oow_t len, char_type c)
@ -504,8 +560,6 @@ exit_point:
fn_split_cstr(hio_split_ucstr, hio_uch_t, hio_is_uch_space, hio_copy_ucstr_unlimited) fn_split_cstr(hio_split_ucstr, hio_uch_t, hio_is_uch_space, hio_copy_ucstr_unlimited)
fn_split_cstr(hio_split_bcstr, hio_bch_t, hio_is_bch_space, hio_copy_bcstr_unlimited) fn_split_cstr(hio_split_bcstr, hio_bch_t, hio_is_bch_space, hio_copy_bcstr_unlimited)
dnl --------------------------------------------------------------------------- dnl ---------------------------------------------------------------------------
define([[fn_chars_to_int]], [[ define([[fn_name]], $1) define([[char_type]], $2) define([[int_type]], $3) define([[fn_chars_to_int]], [[ define([[fn_name]], $1) define([[char_type]], $2) define([[int_type]], $3)
int_type fn_name (const char_type* str, hio_oow_t len, int option, const char_type** endptr, int* is_sober) int_type fn_name (const char_type* str, hio_oow_t len, int option, const char_type** endptr, int* is_sober)