refactor(fileio.c): refactor buf_write_bytes (2)

This commit is contained in:
Lewis Russell
2023-01-30 13:18:00 +00:00
parent f770e05c87
commit 740f6ae168

View File

@@ -3794,51 +3794,41 @@ static int buf_write_convert_with_iconv(struct bw_info *ip, char **bufp, int *le
return OK; return OK;
} }
/// Call write() to write a number of bytes to the file. static int buf_write_convert(struct bw_info *ip, char **bufp, int *lenp)
/// Handles 'encoding' conversion.
///
/// @return FAIL for failure, OK otherwise.
static int buf_write_bytes(struct bw_info *ip)
{ {
char *buf = ip->bw_buf; // data to write
int len = ip->bw_len; // length of data
#ifdef HAS_BW_FLAGS
int flags = ip->bw_flags; // extra flags int flags = ip->bw_flags; // extra flags
#endif
// Skip conversion when writing the BOM.
if (!(flags & FIO_NOCONVERT)) {
if (flags & FIO_UTF8) { if (flags & FIO_UTF8) {
// Convert latin1 in the buffer to UTF-8 in the file. // Convert latin1 in the buffer to UTF-8 in the file.
char *p = ip->bw_conv_buf; // translate to buffer char *p = ip->bw_conv_buf; // translate to buffer
for (int wlen = 0; wlen < len; wlen++) { for (int wlen = 0; wlen < *lenp; wlen++) {
p += utf_char2bytes((uint8_t)buf[wlen], p); p += utf_char2bytes((uint8_t)(*bufp)[wlen], p);
} }
buf = ip->bw_conv_buf; *bufp = ip->bw_conv_buf;
len = (int)(p - ip->bw_conv_buf); *lenp = (int)(p - ip->bw_conv_buf);
} else if (flags & (FIO_UCS4 | FIO_UTF16 | FIO_UCS2 | FIO_LATIN1)) { } else if (flags & (FIO_UCS4 | FIO_UTF16 | FIO_UCS2 | FIO_LATIN1)) {
unsigned c; unsigned c;
int n = 0; int n = 0;
// Convert UTF-8 bytes in the buffer to UCS-2, UCS-4, UTF-16 or // Convert UTF-8 bytes in the buffer to UCS-2, UCS-4, UTF-16 or
// Latin1 chars in the file. // Latin1 chars in the file.
// translate in-place (can only get shorter) or to buffer // translate in-place (can only get shorter) or to buffer
char *p = flags & FIO_LATIN1 ? buf : ip->bw_conv_buf; char *p = flags & FIO_LATIN1 ? *bufp : ip->bw_conv_buf;
for (int wlen = 0; wlen < len; wlen += n) { for (int wlen = 0; wlen < *lenp; wlen += n) {
if (wlen == 0 && ip->bw_restlen != 0) { if (wlen == 0 && ip->bw_restlen != 0) {
// Use remainder of previous call. Append the start of // Use remainder of previous call. Append the start of
// buf[] to get a full sequence. Might still be too // buf[] to get a full sequence. Might still be too
// short! // short!
int l = MIN(len, CONV_RESTLEN - ip->bw_restlen); int l = MIN(*lenp, CONV_RESTLEN - ip->bw_restlen);
memmove(ip->bw_rest + ip->bw_restlen, buf, (size_t)l); memmove(ip->bw_rest + ip->bw_restlen, *bufp, (size_t)l);
n = utf_ptr2len_len((char *)ip->bw_rest, ip->bw_restlen + l); n = utf_ptr2len_len((char *)ip->bw_rest, ip->bw_restlen + l);
if (n > ip->bw_restlen + len) { if (n > ip->bw_restlen + *lenp) {
// We have an incomplete byte sequence at the end to // We have an incomplete byte sequence at the end to
// be written. We can't convert it without the // be written. We can't convert it without the
// remaining bytes. Keep them for the next call. // remaining bytes. Keep them for the next call.
if (ip->bw_restlen + len > CONV_RESTLEN) { if (ip->bw_restlen + *lenp > CONV_RESTLEN) {
return FAIL; return FAIL;
} }
ip->bw_restlen += len; ip->bw_restlen += *lenp;
break; break;
} }
if (n > 1) { if (n > 1) {
@@ -3856,23 +3846,23 @@ static int buf_write_bytes(struct bw_info *ip)
n = 0; n = 0;
} }
} else { } else {
n = utf_ptr2len_len(buf + wlen, len - wlen); n = utf_ptr2len_len(*bufp + wlen, *lenp - wlen);
if (n > len - wlen) { if (n > *lenp - wlen) {
// We have an incomplete byte sequence at the end to // We have an incomplete byte sequence at the end to
// be written. We can't convert it without the // be written. We can't convert it without the
// remaining bytes. Keep them for the next call. // remaining bytes. Keep them for the next call.
if (len - wlen > CONV_RESTLEN) { if (*lenp - wlen > CONV_RESTLEN) {
return FAIL; return FAIL;
} }
ip->bw_restlen = len - wlen; ip->bw_restlen = *lenp - wlen;
memmove(ip->bw_rest, buf + wlen, memmove(ip->bw_rest, *bufp + wlen,
(size_t)ip->bw_restlen); (size_t)ip->bw_restlen);
break; break;
} }
if (n > 1) { if (n > 1) {
c = (unsigned)utf_ptr2char(buf + wlen); c = (unsigned)utf_ptr2char(*bufp + wlen);
} else { } else {
c = (uint8_t)buf[wlen]; c = (uint8_t)(*bufp)[wlen];
} }
} }
@@ -3885,18 +3875,39 @@ static int buf_write_bytes(struct bw_info *ip)
} }
} }
if (flags & FIO_LATIN1) { if (flags & FIO_LATIN1) {
len = (int)(p - buf); *lenp = (int)(p - *bufp);
} else { } else {
buf = ip->bw_conv_buf; *bufp = ip->bw_conv_buf;
len = (int)(p - ip->bw_conv_buf); *lenp = (int)(p - ip->bw_conv_buf);
} }
} }
if (ip->bw_iconv_fd != (iconv_t)-1) { if (ip->bw_iconv_fd != (iconv_t)-1) {
if (buf_write_convert_with_iconv(ip, &buf, &len) == FAIL) { if (buf_write_convert_with_iconv(ip, bufp, lenp) == FAIL) {
return FAIL; return FAIL;
} }
} }
return OK;
}
/// Call write() to write a number of bytes to the file.
/// Handles 'encoding' conversion.
///
/// @return FAIL for failure, OK otherwise.
static int buf_write_bytes(struct bw_info *ip)
{
char *buf = ip->bw_buf; // data to write
int len = ip->bw_len; // length of data
#ifdef HAS_BW_FLAGS
int flags = ip->bw_flags; // extra flags
#endif
// Skip conversion when writing the BOM.
if (!(flags & FIO_NOCONVERT)) {
if (buf_write_convert(ip, &buf, &len) == FAIL) {
return FAIL;
}
} }
if (ip->bw_fd < 0) { if (ip->bw_fd < 0) {