mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-09 01:18:00 +00:00
4f756d2a4d
The previous mb_to_wc and wc_to_mb had horrible and also buggy APIs. This commit introduces a fresh pair of functions to replace them, which generate output by writing to a BinarySink. So it's now up to the caller to decide whether it wants the output written to a fixed-size buffer with overflow checking (via buffer_sink), or dynamically allocated, or even written directly to some other output channel. Nothing uses the new functions yet. I plan to migrate things over in upcoming commits. What was wrong with the old APIs: they had that awkward undocumented Windows-specific 'flags' parameter that I described in the previous commit and took out of the dup_X_to_Y wrappers. But much worse, the semantics for buffer overflow were not just undocumented but actually inconsistent. dup_wc_to_mb() in utils assumed that the underlying wc_to_mb would fill the buffer nearly full and return the size of data it wrote. In fact, this was untrue in the case where wc_to_mb called WideCharToMultiByte: that returns straight-up failure, setting the Windows error code to ERROR_INSUFFICIENT_BUFFER. It _does_ partially fill the output buffer, but doesn't tell you how much it wrote! What's wrong with the new API: it's a bit awkward to write a sequence of wchar_t in native byte order to a byte-oriented BinarySink, so people using put_mb_to_wc directly have to do some annoying pointer casting. But I think that's less horrible than the previous APIs. Another change: in the new API for wc_to_mb, defchr can be "", but not NULL.
29 lines
788 B
C
29 lines
788 B
C
/*
|
|
* dup_wc_to_mb: memory-allocating wrapper on wc_to_mb.
|
|
*
|
|
* Also dup_wc_to_mb_c: same but you already know the length of the
|
|
* wide string, and you get told the length of the returned string.
|
|
* (But it's still NUL-terminated, for convenience.).
|
|
*/
|
|
|
|
#include <wchar.h>
|
|
|
|
#include "putty.h"
|
|
#include "misc.h"
|
|
|
|
char *dup_wc_to_mb_c(int codepage, const wchar_t *string,
|
|
size_t inlen, const char *defchr, size_t *outlen_p)
|
|
{
|
|
strbuf *sb = strbuf_new();
|
|
put_wc_to_mb(sb, codepage, string, inlen, defchr);
|
|
if (outlen_p)
|
|
*outlen_p = sb->len;
|
|
return strbuf_to_str(sb);
|
|
}
|
|
|
|
char *dup_wc_to_mb(int codepage, const wchar_t *string,
|
|
const char *defchr)
|
|
{
|
|
return dup_wc_to_mb_c(codepage, string, wcslen(string), defchr, NULL);
|
|
}
|