mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
refactor(fileio.c): refactor buf_write_bytes
This commit is contained in:
parent
99149153c4
commit
f770e05c87
@ -3733,6 +3733,67 @@ static bool time_differs(const FileInfo *file_info, long mtime, long mtime_ns) F
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int buf_write_convert_with_iconv(struct bw_info *ip, char **bufp, int *lenp)
|
||||||
|
{
|
||||||
|
const char *from;
|
||||||
|
size_t fromlen;
|
||||||
|
size_t tolen;
|
||||||
|
|
||||||
|
int len = *lenp;
|
||||||
|
|
||||||
|
// Convert with iconv().
|
||||||
|
if (ip->bw_restlen > 0) {
|
||||||
|
// Need to concatenate the remainder of the previous call and
|
||||||
|
// the bytes of the current call. Use the end of the
|
||||||
|
// conversion buffer for this.
|
||||||
|
fromlen = (size_t)len + (size_t)ip->bw_restlen;
|
||||||
|
char *fp = ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
|
||||||
|
memmove(fp, ip->bw_rest, (size_t)ip->bw_restlen);
|
||||||
|
memmove(fp + ip->bw_restlen, *bufp, (size_t)len);
|
||||||
|
from = fp;
|
||||||
|
tolen = ip->bw_conv_buflen - fromlen;
|
||||||
|
} else {
|
||||||
|
from = *bufp;
|
||||||
|
fromlen = (size_t)len;
|
||||||
|
tolen = ip->bw_conv_buflen;
|
||||||
|
}
|
||||||
|
char *to = ip->bw_conv_buf;
|
||||||
|
|
||||||
|
if (ip->bw_first) {
|
||||||
|
size_t save_len = tolen;
|
||||||
|
|
||||||
|
// output the initial shift state sequence
|
||||||
|
(void)iconv(ip->bw_iconv_fd, NULL, NULL, &to, &tolen);
|
||||||
|
|
||||||
|
// There is a bug in iconv() on Linux (which appears to be
|
||||||
|
// wide-spread) which sets "to" to NULL and messes up "tolen".
|
||||||
|
if (to == NULL) {
|
||||||
|
to = ip->bw_conv_buf;
|
||||||
|
tolen = save_len;
|
||||||
|
}
|
||||||
|
ip->bw_first = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If iconv() has an error or there is not enough room, fail.
|
||||||
|
if ((iconv(ip->bw_iconv_fd, (void *)&from, &fromlen, &to, &tolen)
|
||||||
|
== (size_t)-1 && ICONV_ERRNO != ICONV_EINVAL)
|
||||||
|
|| fromlen > CONV_RESTLEN) {
|
||||||
|
ip->bw_conv_error = true;
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy remainder to ip->bw_rest[] to be used for the next call.
|
||||||
|
if (fromlen > 0) {
|
||||||
|
memmove(ip->bw_rest, (void *)from, fromlen);
|
||||||
|
}
|
||||||
|
ip->bw_restlen = (int)fromlen;
|
||||||
|
|
||||||
|
*bufp = ip->bw_conv_buf;
|
||||||
|
*lenp = (int)(to - ip->bw_conv_buf);
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
/// Call write() to write a number of bytes to the file.
|
/// Call write() to write a number of bytes to the file.
|
||||||
/// Handles 'encoding' conversion.
|
/// Handles 'encoding' conversion.
|
||||||
///
|
///
|
||||||
@ -3832,59 +3893,9 @@ static int buf_write_bytes(struct bw_info *ip)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ip->bw_iconv_fd != (iconv_t)-1) {
|
if (ip->bw_iconv_fd != (iconv_t)-1) {
|
||||||
const char *from;
|
if (buf_write_convert_with_iconv(ip, &buf, &len) == FAIL) {
|
||||||
size_t fromlen;
|
|
||||||
size_t tolen;
|
|
||||||
|
|
||||||
// Convert with iconv().
|
|
||||||
if (ip->bw_restlen > 0) {
|
|
||||||
// Need to concatenate the remainder of the previous call and
|
|
||||||
// the bytes of the current call. Use the end of the
|
|
||||||
// conversion buffer for this.
|
|
||||||
fromlen = (size_t)len + (size_t)ip->bw_restlen;
|
|
||||||
char *fp = ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
|
|
||||||
memmove(fp, ip->bw_rest, (size_t)ip->bw_restlen);
|
|
||||||
memmove(fp + ip->bw_restlen, buf, (size_t)len);
|
|
||||||
from = fp;
|
|
||||||
tolen = ip->bw_conv_buflen - fromlen;
|
|
||||||
} else {
|
|
||||||
from = buf;
|
|
||||||
fromlen = (size_t)len;
|
|
||||||
tolen = ip->bw_conv_buflen;
|
|
||||||
}
|
|
||||||
char *to = ip->bw_conv_buf;
|
|
||||||
|
|
||||||
if (ip->bw_first) {
|
|
||||||
size_t save_len = tolen;
|
|
||||||
|
|
||||||
// output the initial shift state sequence
|
|
||||||
(void)iconv(ip->bw_iconv_fd, NULL, NULL, &to, &tolen);
|
|
||||||
|
|
||||||
// There is a bug in iconv() on Linux (which appears to be
|
|
||||||
// wide-spread) which sets "to" to NULL and messes up "tolen".
|
|
||||||
if (to == NULL) {
|
|
||||||
to = ip->bw_conv_buf;
|
|
||||||
tolen = save_len;
|
|
||||||
}
|
|
||||||
ip->bw_first = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If iconv() has an error or there is not enough room, fail.
|
|
||||||
if ((iconv(ip->bw_iconv_fd, (void *)&from, &fromlen, &to, &tolen)
|
|
||||||
== (size_t)-1 && ICONV_ERRNO != ICONV_EINVAL)
|
|
||||||
|| fromlen > CONV_RESTLEN) {
|
|
||||||
ip->bw_conv_error = true;
|
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy remainder to ip->bw_rest[] to be used for the next call.
|
|
||||||
if (fromlen > 0) {
|
|
||||||
memmove(ip->bw_rest, (void *)from, fromlen);
|
|
||||||
}
|
|
||||||
ip->bw_restlen = (int)fromlen;
|
|
||||||
|
|
||||||
buf = ip->bw_conv_buf;
|
|
||||||
len = (int)(to - ip->bw_conv_buf);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user