char * rxvt_wcstombs (const wchar_t *str, int len) { if (len < 0) len = wcslen (str); mbstate mbs; char *r = (char *)rxvt_malloc (len * MB_CUR_MAX + 1); char *dst = r; while (len--) { ssize_t l = wcrtomb (dst, *str++, mbs); if (l < 0) { *dst++ = '?'; wcrtomb (0, 0, mbs); // reset undefined state } else dst += l; } *dst++ = 0; return (char *)rxvt_realloc (r, dst - r); }
static int do_test (void) { unsigned char buf[7] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; const unsigned char bufcheck[7] = { 0x25, 0xe2, 0x82, 0xac, 0xce, 0xbb, 0 }; const wchar_t srcbuf[4] = { 0x25, 0x20ac, 0x03bb, 0 }; mbstate_t state; const wchar_t *src; char *dst; int result = 0; const char *used_locale; setlocale (LC_CTYPE, "de_DE.UTF-8"); /* Double check. */ used_locale = setlocale (LC_CTYPE, NULL); printf ("used locale: \"%s\"\n", used_locale); result = strcmp (used_locale, "de_DE.UTF-8"); memset (&state, '\0', sizeof (state)); src = srcbuf; dst = (char *) buf; show (wcrtomb (dst, *src++, &state), 1, buf + 1); show (wcrtomb (dst, *src++, &state), 3, buf + 4); show (wcrtomb (dst, *src++, &state), 2, buf + 6); show (wcrtomb (dst, *src, &state), 1, buf + 7); if (memcmp (buf, bufcheck, 7)) { puts ("wrong results"); result = 1; } return result; }
static int print_macro (FILE *f, int maxwidth, const char **macro) { int n = maxwidth; wchar_t wc; int w; size_t k; size_t len = mutt_strlen (*macro); mbstate_t mbstate1, mbstate2; memset (&mbstate1, 0, sizeof (mbstate1)); memset (&mbstate2, 0, sizeof (mbstate2)); for (; len && (k = mbrtowc (&wc, *macro, len, &mbstate1)); *macro += k, len -= k) { if (k == (size_t)(-1) || k == (size_t)(-2)) { k = (k == (size_t)(-1)) ? 1 : len; wc = replacement_char (); } /* glibc-2.1.3's wcwidth() returns 1 for unprintable chars! */ if (IsWPrint (wc) && (w = wcwidth (wc)) >= 0) { if (w > n) break; n -= w; { char buf[MB_LEN_MAX*2]; size_t n1, n2; if ((n1 = wcrtomb (buf, wc, &mbstate2)) != (size_t)(-1) && (n2 = wcrtomb (buf + n1, 0, &mbstate2)) != (size_t)(-1)) fputs (buf, f); } } else if (wc < 0x20 || wc == 0x7f) { if (2 > n) break; n -= 2; if (wc == '\033') fprintf (f, "\\e"); else if (wc == '\n') fprintf (f, "\\n"); else if (wc == '\r') fprintf (f, "\\r"); else if (wc == '\t') fprintf (f, "\\t"); else fprintf (f, "^%c", (char)((wc + '@') & 0x7f)); } else { if (1 > n) break; n -= 1; fprintf (f, "?"); } } return (maxwidth - n); }
unsigned long ILAnsiGetByteCount(const unsigned short *chars, unsigned long count) { #ifdef IL_CONFIG_LATIN1 return count; #else #if HAVE_WCRTOMB /* Use the re-entrant function to perform the conversion */ mbstate_t state; char buf[MB_LEN_MAX+1]; size_t chlen; unsigned short ch; unsigned long len = 0; ILMemZero(&state, sizeof(state)); wcrtomb(buf, 0, &state); while(count > 0) { ch = *chars++; if(ch != 0) { chlen = wcrtomb(buf, (wchar_t)ch, &state); if(chlen != (size_t)(-1)) { len += (unsigned long)chlen; } } else { ++len; } --count; } return len; #else /* Use the non re-entrant function to perform the conversion and just hope that the underlying libc takes care of the thread-safety issues for us */ char buf[MB_LEN_MAX+1]; int chlen; unsigned long len = 0; wctomb((char *)0, 0); while(count > 0) { chlen = wctomb(buf, (wchar_t)(*chars)); if(chlen > 0) { len += (unsigned long)chlen; } ++chars; --count; } return len; #endif #endif }
/** * Return true if the input wide-character is one of the special * characters used to define the syntax of the dictionary. */ static int is_special(wchar_t wc, mbstate_t *ps) { char buff[MB_LEN_MAX]; int nr = wcrtomb(buff, wc, ps); if (1 != nr) return FALSE; return (NULL != strchr(SPECIAL, buff[0])); }
/* EXTPROTO */ char* rxvt_wcstombs (const wchar_t* str, int len) { mbstate_t mbs; char* r; char* dst; if (len < 0) len = wcslen (str); memset (&mbs, 0, sizeof (mbs)); r = (char *)rxvt_malloc (len * MB_CUR_MAX + 1); dst = r; while (len--) { int l = wcrtomb (dst, *str++, &mbs); if (l < 0) *dst++ = '?'; else dst += l; } *dst++ = 0; return r; }
static int do_test (const char *loc) { char buf[100]; size_t n; mbstate_t state; const char *nloc; int res; nloc = setlocale (LC_ALL, loc); if (nloc == NULL) { printf ("could not set locale \"%s\"\n", loc); return 1; } printf ("new locale: %s\n", nloc); memset (&state, '\0', sizeof (state)); errno = 0; n = wcrtomb (buf, (wchar_t) -15l, &state); printf ("n = %zd, errno = %d (%s)\n", n, errno, strerror (errno)); res = n != (size_t) -1 || errno != EILSEQ; if (res) puts ("*** FAIL"); putchar ('\n'); return res; }
/* * Like __fputwc_unlock, but handles fake string (__SSTR) files properly. * File must already be locked. */ static wint_t __xfputwc(wchar_t wc, FILE *fp, locale_t locale) { mbstate_t mbs; char buf[MB_LEN_MAX]; struct __suio uio; struct __siov iov; size_t len; if ((fp->_flags & __SSTR) == 0) return (__fputwc_unlock(wc, fp, locale)); memset(&mbs, 0, sizeof(mbs)); len = wcrtomb(buf, wc, &mbs); if (len == (size_t)-1) { fp->_flags |= __SERR; errno = EILSEQ; return (WEOF); } uio.uio_iov = &iov; uio.uio_resid = len; uio.uio_iovcnt = 1; iov.iov_base = buf; iov.iov_len = len; return (__sfvwrite(fp, &uio) != EOF ? (wint_t)wc : WEOF); }
int __printf_render_chr(struct __printf_io *io, const struct printf_info *pi, const void *const *arg) { int i; wint_t ii; unsigned char c; static const mbstate_t initial; /* XXX: this is bogus! */ mbstate_t mbs; size_t mbseqlen; char buf[MB_CUR_MAX]; if (pi->is_long || pi->spec == 'C') { ii = *((wint_t *)arg[0]); mbs = initial; mbseqlen = wcrtomb(buf, (wchar_t)ii, &mbs); if (mbseqlen == (size_t) -1) return (-1); return (__printf_out(io, pi, buf, mbseqlen)); } i = *((int *)arg[0]); c = i; i = __printf_out(io, pi, &c, 1); __printf_flush(io); return (i); }
wadd_wch(WINDOW *win, const cchar_t *wch) { PUTC_DATA; int n; int code = ERR; TR(TRACE_VIRTPUT | TRACE_CCALLS, (T_CALLED("wadd_wch(%p, %s)"), win, _tracech_t(wch))); if (win != 0) { PUTC_INIT; for (PUTC_i = 0; PUTC_i < CCHARW_MAX; ++PUTC_i) { attr_t attrs = (wch->attr & A_ATTRIBUTES); if ((PUTC_ch = wch->chars[PUTC_i]) == L'\0') break; if ((PUTC_n = wcrtomb(PUTC_buf, PUTC_ch, &PUT_st)) <= 0) { code = ERR; if (is8bits(PUTC_ch)) code = waddch(win, UChar(PUTC_ch) | attrs); break; } for (n = 0; n < PUTC_n; n++) { if ((code = waddch(win, UChar(PUTC_buf[n]) | attrs)) == ERR) { break; } } if (code == ERR) break; } } TR(TRACE_VIRTPUT | TRACE_CCALLS, (T_RETURN("%d"), code)); return (code); }
wecho_wchar(WINDOW *win, const cchar_t * wch) { PUTC_DATA; int n; int code = ERR; TR(TRACE_VIRTPUT | TRACE_CCALLS, (T_CALLED("wecho_wchar(%p, %s)"), win, _tracech_t(wch))); if (win != 0) { PUTC_INIT; while (PUTC_i < CCHARW_MAX) { if ((PUTC_ch = wch->chars[PUTC_i++]) == L'\0') break; if ((PUTC_n = wcrtomb(PUTC_buf, PUTC_ch, &PUT_st)) <= 0) { code = ERR; if (is8bits(PUTC_ch)) code = waddch(win, UChar(PUTC_ch) | wch->attr); break; } for (n = 0; n < PUTC_n; n++) { if ((code = waddch(win, UChar(PUTC_buf[n]) | wch->attr)) == ERR) { break; } } if (code == ERR) break; } wrefresh(win); } TR(TRACE_VIRTPUT | TRACE_CCALLS, (T_RETURN("%d"), code)); return (code); }
void ui_init(bool force_ascii) { // Cell character 0 is always a space strcpy(ui_chars[0], " "); #ifdef __STDC_ISO_10646__ if (force_ascii) { ui_ascii = true; return; } // Encode Unicode cell characters using system locale char *origLocale = setlocale(LC_CTYPE, NULL); setlocale(LC_CTYPE, ""); int ch; mbstate_t mbs; memset(&mbs, 0, sizeof mbs); for (ch = 1; ch < NCHARS; ch++) { int len = wcrtomb(ui_chars[ch], 0x2580 + ch, &mbs); if (len == -1 || !mbsinit(&mbs)) { ui_ascii = true; break; } ui_chars[ch][len] = 0; } // Restore the original locale setlocale(LC_CTYPE, origLocale); #else ui_ascii = true; #endif }
/* * Update the current column position for a character. */ static int newpos(int col, wint_t ch) { char buf[MB_LEN_MAX]; size_t len; int w; if (bflag) { len = wcrtomb(buf, ch, NULL); col += len; } else switch (ch) { case '\b': if (col > 0) --col; break; case '\r': col = 0; break; case '\t': col = (col + 8) & ~7; break; default: if ((w = wcwidth(ch)) > 0) col += w; break; } return (col); }
static __inline int convert_string(FILE *fp, char * mbp, int width, locale_t locale) { mbstate_t mbs; size_t nconv; wint_t wi; int nread; mbs = initial_mbs; nread = 0; while ((wi = __fgetwc(fp, locale)) != WEOF && width-- != 0 && !iswspace(wi)) { if (mbp != SUPPRESS_PTR) { nconv = wcrtomb(mbp, wi, &mbs); if (nconv == (size_t)-1) return (-1); mbp += nconv; } nread++; } if (wi != WEOF) __ungetwc(wi, fp, locale); if (mbp != SUPPRESS_PTR) *mbp = 0; return (nread); }
static __inline int convert_ccl(FILE *fp, char * mbp, int width, const struct ccl *ccl, locale_t locale) { mbstate_t mbs; size_t nconv; wint_t wi; int n; n = 0; mbs = initial_mbs; while ((wi = __fgetwc(fp, locale)) != WEOF && width-- != 0 && inccl(ccl, wi)) { if (mbp != SUPPRESS_PTR) { nconv = wcrtomb(mbp, wi, &mbs); if (nconv == (size_t)-1) return (-1); mbp += nconv; } n++; } if (wi != WEOF) __ungetwc(wi, fp, locale); if (mbp != SUPPRESS_PTR) *mbp = 0; return (n); }
/* Convert the *N-byte string, BEG, to lowercase, and write the NUL-terminated result into malloc'd storage. Upon success, set *N to the length (in bytes) of the resulting string (not including the trailing NUL byte), and return a pointer to the lowercase string. Upon memory allocation failure, this function exits. Note that on input, *N must be larger than zero. Note that while this function returns a pointer to malloc'd storage, the caller must not free it, since this function retains a pointer to the buffer and reuses it on any subsequent call. As a consequence, this function is not thread-safe. */ char * mbtolower (const char *beg, size_t *n) { static char *out; static size_t outalloc; size_t outlen, mb_cur_max; mbstate_t is, os; const char *end; char *p; assert (0 < *n); if (*n > outalloc) { out = xrealloc (out, *n); outalloc = *n; } /* appease clang-2.6 */ assert (out); memset (&is, 0, sizeof (is)); memset (&os, 0, sizeof (os)); end = beg + *n; mb_cur_max = MB_CUR_MAX; p = out; outlen = 0; while (beg < end) { wchar_t wc; size_t mbclen = mbrtowc(&wc, beg, end - beg, &is); if (outlen + mb_cur_max >= outalloc) { out = x2nrealloc (out, &outalloc, 1); p = out + outlen; } if (mbclen == (size_t) -1 || mbclen == (size_t) -2 || mbclen == 0) { /* An invalid sequence, or a truncated multi-octet character. We treat it as a single-octet character. */ *p++ = *beg++; outlen++; memset (&is, 0, sizeof (is)); memset (&os, 0, sizeof (os)); } else { beg += mbclen; mbclen = wcrtomb (p, towlower ((wint_t) wc), &os); p += mbclen; outlen += mbclen; } } *n = p - out; *p = 0; return out; }
_tracecchar_t2(int bufnum, const cchar_t *ch) { char *result = _nc_trace_buf(bufnum, BUFSIZ); attr_t attr; const char *found; if (result != 0) { strcpy(result, l_brace); if (ch != 0) { attr = AttrOfD(ch); if ((found = _nc_altcharset_name(attr, (chtype) CharOfD(ch))) != 0) { (void) _nc_trace_bufcat(bufnum, found); attr &= ~A_ALTCHARSET; } else if (isWidecExt(CHDEREF(ch))) { (void) _nc_trace_bufcat(bufnum, "{NAC}"); attr &= ~A_CHARTEXT; } else { PUTC_DATA; int n; PUTC_INIT; (void) _nc_trace_bufcat(bufnum, "{ "); for (PUTC_i = 0; PUTC_i < CCHARW_MAX; ++PUTC_i) { PUTC_ch = ch->chars[PUTC_i]; if (PUTC_ch == L'\0') { if (PUTC_i == 0) result = _nc_trace_bufcat(bufnum, "\\000"); break; } PUTC_n = wcrtomb(PUTC_buf, ch->chars[PUTC_i], &PUT_st); if (PUTC_n <= 0) { if (PUTC_ch != L'\0') { /* it could not be a multibyte sequence */ (void) _nc_trace_bufcat(bufnum, _nc_tracechar(CURRENT_SCREEN, UChar(ch->chars[PUTC_i]))); } break; } for (n = 0; n < PUTC_n; n++) { if (n) (void) _nc_trace_bufcat(bufnum, ", "); (void) _nc_trace_bufcat(bufnum, _nc_tracechar(CURRENT_SCREEN, UChar(PUTC_buf[n]))); } } (void) _nc_trace_bufcat(bufnum, " }"); } if (attr != A_NORMAL) { (void) _nc_trace_bufcat(bufnum, " | "); (void) _nc_trace_bufcat(bufnum, _traceattr2(bufnum + 20, attr)); } } result = _nc_trace_bufcat(bufnum, r_brace); } return result; }
/** * mutt_addwch - addwch would be provided by an up-to-date curses library * @param wc Wide char to display * @retval 0 Success * @retval -1 Error */ int mutt_addwch(wchar_t wc) { char buf[MB_LEN_MAX * 2]; mbstate_t mbstate; size_t n1, n2; memset(&mbstate, 0, sizeof(mbstate)); if (((n1 = wcrtomb(buf, wc, &mbstate)) == (size_t)(-1)) || ((n2 = wcrtomb(buf + n1, 0, &mbstate)) == (size_t)(-1))) { return -1; /* ERR */ } else { return addstr(buf); } }
/* * Convert a wide character string argument for the %ls format to a multibyte * string representation. If not -1, prec specifies the maximum number of * bytes to output, and also means that we can't assume that the wide char * string is null-terminated. */ static char * __wcsconv(wchar_t *wcsarg, int prec) { mbstate_t mbs; char buf[MB_LEN_MAX]; wchar_t *p; char *convbuf; size_t clen, nbytes; /* Allocate space for the maximum number of bytes we could output. */ if (prec < 0) { memset(&mbs, 0, sizeof(mbs)); p = wcsarg; nbytes = wcsrtombs(NULL, (const wchar_t **)&p, 0, &mbs); if (nbytes == (size_t)-1) { errno = EILSEQ; return (NULL); } } else { /* * Optimisation: if the output precision is small enough, * just allocate enough memory for the maximum instead of * scanning the string. */ if (prec < 128) nbytes = prec; else { nbytes = 0; p = wcsarg; memset(&mbs, 0, sizeof(mbs)); for (;;) { clen = wcrtomb(buf, *p++, &mbs); if (clen == 0 || clen == (size_t)-1 || nbytes + clen > (size_t)prec) break; nbytes += clen; } if (clen == (size_t)-1) { errno = EILSEQ; return (NULL); } } } if ((convbuf = malloc(nbytes + 1)) == NULL) return (NULL); /* Fill the output buffer. */ p = wcsarg; memset(&mbs, 0, sizeof(mbs)); if ((nbytes = wcsrtombs(convbuf, (const wchar_t **)&p, nbytes, &mbs)) == (size_t)-1) { free(convbuf); errno = EILSEQ; return (NULL); } convbuf[nbytes] = '\0'; return (convbuf); }
size_t wcsrtombs(char *s, const wchar_t **ws, size_t n, mbstate_t *st) { const wchar_t *ws2; char buf[4]; size_t N = n, l; if (!s) { for (n=0, ws2=*ws; *ws2; ws2++) { if (*ws2 >= 0x80) { l = wcrtomb(buf, *ws2, 0); if (!(l+1)) return -1; n += l; } else n++; } return n; } while (n>=4 && **ws) { if (**ws >= 0x80) { l = wcrtomb(s, **ws, 0); if (!(l+1)) return -1; s += l; n -= l; } else { *s++ = **ws; n--; } (*ws)++; } while (n && **ws) { if (**ws >= 0x80) { l = wcrtomb(buf, **ws, 0); if (!(l+1)) return -1; if (l>n) return N-n; wcrtomb(s, **ws, 0); s += l; n -= l; } else { *s++ = **ws; n--; } (*ws)++; } if (n) *s = 0; *ws = 0; return N-n; }
TEST(wchar, wctomb_wcrtomb) { // wctomb and wcrtomb behave differently when s == NULL. EXPECT_EQ(0, wctomb(NULL, L'h')); EXPECT_EQ(0, wctomb(NULL, L'\0')); EXPECT_EQ(1U, wcrtomb(NULL, L'\0', NULL)); EXPECT_EQ(1U, wcrtomb(NULL, L'h', NULL)); char bytes[MB_LEN_MAX]; // wctomb and wcrtomb behave similarly for the null wide character. EXPECT_EQ(1, wctomb(bytes, L'\0')); EXPECT_EQ(1U, wcrtomb(bytes, L'\0', NULL)); // ...and for regular characters. memset(bytes, 0, sizeof(bytes)); EXPECT_EQ(1, wctomb(bytes, L'h')); EXPECT_EQ('h', bytes[0]); memset(bytes, 0, sizeof(bytes)); EXPECT_EQ(1U, wcrtomb(bytes, L'h', NULL)); EXPECT_EQ('h', bytes[0]); ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8")); uselocale(LC_GLOBAL_LOCALE); // 1-byte UTF-8. memset(bytes, 0, sizeof(bytes)); EXPECT_EQ(1U, wcrtomb(bytes, L'h', NULL)); EXPECT_EQ('h', bytes[0]); // 2-byte UTF-8. memset(bytes, 0, sizeof(bytes)); EXPECT_EQ(2U, wcrtomb(bytes, 0x00a2, NULL)); EXPECT_EQ('\xc2', bytes[0]); EXPECT_EQ('\xa2', bytes[1]); // 3-byte UTF-8. memset(bytes, 0, sizeof(bytes)); EXPECT_EQ(3U, wcrtomb(bytes, 0x20ac, NULL)); EXPECT_EQ('\xe2', bytes[0]); EXPECT_EQ('\x82', bytes[1]); EXPECT_EQ('\xac', bytes[2]); // 4-byte UTF-8. memset(bytes, 0, sizeof(bytes)); EXPECT_EQ(4U, wcrtomb(bytes, 0x24b62, NULL)); EXPECT_EQ('\xf0', bytes[0]); EXPECT_EQ('\xa4', bytes[1]); EXPECT_EQ('\xad', bytes[2]); EXPECT_EQ('\xa2', bytes[3]); // Invalid code point. EXPECT_EQ(static_cast<size_t>(-1), wcrtomb(bytes, 0xffffffff, NULL)); EXPECT_EQ(EILSEQ, errno); }
wchar2bytes(wchar_t wc): bytes(new char[MB_CUR_MAX*2 + sizeof(wchar_t)*2 + 2 + 1]) { mbstate_t ps; memset(&ps, 0, sizeof(ps));//initialize mbstate size_t n; if ((n = wcrtomb(bytes, wc, &ps)) == size_t(-1)) snprintf(bytes, NumberOf(bytes), "U+%04X", int(wc)); else bytes[n] = 0; }
bool make_invalid_wchar(wchar_t &w) { std::setlocale(LC_ALL,"C"); w=(wchar_t)WEOF; std::mbstate_t ps=std::mbstate_t(); char s[MB_LEN_MAX]; size_t r=wcrtomb(s,w,&ps); return r==(size_t)-1; }
static int _inp_printable(const wint_t ch) { char bytes[MB_CUR_MAX+1]; size_t utf_len = wcrtomb(bytes, ch, NULL); bytes[utf_len] = '\0'; gunichar unichar = g_utf8_get_char(bytes); return g_unichar_isprint(unichar) && (ch != KEY_MOUSE); }
static int writeCharacter (const wchar_t *character, mbstate_t *state) { char bytes[0X1000]; size_t result = wcrtomb(bytes, (character? *character: WC_C('\0')), state); if (result == (size_t)-1) return 0; if (!character) result -= 1; fwrite(bytes, 1, result, outputStream); return !ferror(outputStream); }
/* Check the multibyte character s[0..n-1]. */ static void check_character (const char *s, size_t n) { wchar_t wc; char buf[64]; int iret; size_t ret; wc = (wchar_t) 0xBADFACE; iret = mbtowc (&wc, s, n); ASSERT (iret == n); ret = wcrtomb (buf, wc, NULL); ASSERT (ret == n); ASSERT (memcmp (buf, s, n) == 0); /* Test special calling convention, passing a NULL pointer. */ ret = wcrtomb (NULL, wc, NULL); ASSERT (ret == 1); }
static int really_getch(WINDOW *win, int *fkey) { int ch; #ifdef USE_WIDE_CURSES int code; mbstate_t state; wchar_t my_wchar; wint_t my_wint; /* * We get a wide character, translate it to multibyte form to avoid * having to change the rest of the code to use wide-characters. */ if (used_last_getc >= have_last_getc) { used_last_getc = 0; have_last_getc = 0; ch = ERR; *fkey = 0; code = wget_wch(win, &my_wint); my_wchar = (wchar_t) my_wint; switch (code) { case KEY_CODE_YES: ch = *fkey = my_wchar; last_getc = my_wchar; break; case OK: memset(&state, 0, sizeof(state)); have_last_getc = (int) wcrtomb(last_getc_bytes, my_wchar, &state); if (have_last_getc < 0) { have_last_getc = used_last_getc = 0; last_getc_bytes[0] = (char) my_wchar; } ch = (int) CharOf(last_getc_bytes[used_last_getc++]); last_getc = my_wchar; break; case ERR: ch = ERR; last_getc = ERR; break; default: break; } } else { ch = (int) CharOf(last_getc_bytes[used_last_getc++]); } #else ch = wgetch(win); last_getc = ch; *fkey = (ch > KEY_MIN && ch < KEY_MAX); #endif return ch; }
int wctob(wint_t wc) { mbstate_t ps; memset(&ps, 0, sizeof(ps)); char mb[MB_CUR_MAX]; int saved_errno = errno; size_t status = wcrtomb(mb, wc, &ps); if ( status == (size_t) -1 ) return errno = saved_errno, EOF; if ( 2 <= status ) return EOF; return (int) (unsigned char) mb[0]; }
TEST(wchar, wcrtomb_start_state) { char out[MB_LEN_MAX]; mbstate_t ps; // Any non-initial state is invalid when calling wcrtomb. memset(&ps, 0, sizeof(ps)); EXPECT_EQ(static_cast<size_t>(-2), mbrtowc(NULL, "\xc2", 1, &ps)); EXPECT_EQ(static_cast<size_t>(-1), wcrtomb(out, 0x00a2, &ps)); EXPECT_EQ(EILSEQ, errno); // If the first argument to wcrtomb is NULL or the second is L'\0' the shift // state should be reset. memset(&ps, 0, sizeof(ps)); EXPECT_EQ(static_cast<size_t>(-2), mbrtowc(NULL, "\xc2", 1, &ps)); EXPECT_EQ(1U, wcrtomb(NULL, 0x00a2, &ps)); EXPECT_TRUE(mbsinit(&ps)); memset(&ps, 0, sizeof(ps)); EXPECT_EQ(static_cast<size_t>(-2), mbrtowc(NULL, "\xf0\xa4", 1, &ps)); EXPECT_EQ(1U, wcrtomb(out, L'\0', &ps)); EXPECT_TRUE(mbsinit(&ps)); }
static void h_wctomb(const struct test *t, char tc) { wchar_t wcs[16 + 2]; char buf[128]; char cs[MB_LEN_MAX]; const char *pcs; char *str; mbstate_t st; mbstate_t *stp = NULL; size_t sz, ret, i; ATF_REQUIRE_STREQ(setlocale(LC_ALL, "C"), "C"); ATF_REQUIRE(setlocale(LC_CTYPE, t->locale) != NULL); (void)strvis(buf, t->data, VIS_WHITE | VIS_OCTAL); (void)printf("Checking sequence: \"%s\"\n", buf); ATF_REQUIRE((str = setlocale(LC_ALL, NULL)) != NULL); (void)printf("Using locale: %s\n", str); if (tc == TC_WCRTOMB_ST) { (void)memset(&st, 0, sizeof(st)); stp = &st; } wcs[t->wclen] = L'X'; /* poison */ pcs = t->data; sz = mbsrtowcs(wcs, &pcs, t->wclen + 2, NULL); ATF_REQUIRE_EQ_MSG(sz, t->wclen, "mbsrtowcs() returned: " "%zu, expected: %zu", sz, t->wclen); ATF_REQUIRE_EQ(wcs[t->wclen], 0); for (i = 0; i < t->wclen + 1; i++) { if (tc == TC_WCTOMB) ret = wctomb(cs, wcs[i]); else ret = wcrtomb(cs, wcs[i], stp); if (ret == t->mblen[i]) continue; (void)printf("At position %zd:\n", i); (void)printf(" expected: %zd\n", t->mblen[i]); (void)printf(" got : %zd\n", ret); atf_tc_fail("Test failed"); /* NOTREACHED */ } (void)printf("Ok.\n"); }