rktio: more text-mode repairs
This commit is contained in:
parent
b96fc45133
commit
4250d51f08
|
@ -40,7 +40,8 @@ struct rktio_fd_t {
|
||||||
struct Win_FD_Output_Thread *oth; /* output mode */
|
struct Win_FD_Output_Thread *oth; /* output mode */
|
||||||
int unblocked; /* whether non-blocking mode is installed */
|
int unblocked; /* whether non-blocking mode is installed */
|
||||||
char *buffer; /* shared with reading thread */
|
char *buffer; /* shared with reading thread */
|
||||||
int pending_cr; /* for text-mode input, may be dropped by a following lf */
|
int has_pending_byte; /* for text-mode input, may be dropped by a following lf */
|
||||||
|
int pending_byte; /* for text-mode input, either a CR waiting to decode, or byte that didn't fit */
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -120,9 +121,12 @@ static CSI_proc get_csi(void)
|
||||||
return csi;
|
return csi;
|
||||||
}
|
}
|
||||||
|
|
||||||
static intptr_t rktio_adjust_input_text(rktio_fd_t *rfd, char *buffer, char *is_cnoverted, intptr_t got);
|
static intptr_t adjust_input_text(rktio_fd_t *rfd, char *buffer, char *is_converted,
|
||||||
static const char *rktio_adjust_output_text(const char *buffer, intptr_t *towrite);
|
intptr_t got, intptr_t offset);
|
||||||
static intptr_t rktio_recount_output_text(const char *orig_buffer, const char *buffer, intptr_t wrote);
|
static intptr_t adjust_input_text_for_pending_cr(rktio_fd_t *rfd, char *buffer, char *is_converted,
|
||||||
|
intptr_t got);
|
||||||
|
static const char *adjust_output_text(const char *buffer, intptr_t *towrite);
|
||||||
|
static intptr_t recount_output_text(const char *orig_buffer, const char *buffer, intptr_t wrote);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -775,31 +779,41 @@ intptr_t rktio_read_converted(rktio_t *rktio, rktio_fd_t *rfd, char *buffer, int
|
||||||
if (!rfd->th) {
|
if (!rfd->th) {
|
||||||
/* We can read directly. This must be a regular file, where
|
/* We can read directly. This must be a regular file, where
|
||||||
reading never blocks. */
|
reading never blocks. */
|
||||||
DWORD rgot;
|
DWORD rgot, offset = 0;
|
||||||
|
|
||||||
if (rfd->pending_cr && len) {
|
if (rfd->has_pending_byte) {
|
||||||
/* just in case we need to add the cr */
|
if (!len)
|
||||||
len--;
|
return 0;
|
||||||
|
buffer[0] = rfd->pending_byte;
|
||||||
|
if (len == 1) {
|
||||||
|
if (rfd->pending_byte == '\r') {
|
||||||
|
/* We have to read one more byte and then decode,
|
||||||
|
shifting the new byte into pending position
|
||||||
|
if it's not '\n' */
|
||||||
|
} else {
|
||||||
|
if (is_converted) is_converted[0] = 0;
|
||||||
|
rfd->has_pending_byte = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* read after first byte installed into the buffer */
|
||||||
|
offset = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ReadFile((HANDLE)rfd->fd, buffer, len, &rgot, NULL)) {
|
if (!ReadFile((HANDLE)rfd->fd, buffer + offset, len - offset, &rgot, NULL)) {
|
||||||
get_windows_error();
|
get_windows_error();
|
||||||
return RKTIO_READ_ERROR;
|
return RKTIO_READ_ERROR;
|
||||||
}
|
}
|
||||||
|
rgot += offset;
|
||||||
|
|
||||||
if (!rgot) {
|
if (rfd->has_pending_byte) {
|
||||||
if (rfd->pending_cr) {
|
/* We had a buffer of size 1 and a pending '\r'... */
|
||||||
if (len) {
|
return adjust_input_text_for_pending_cr(rfd, buffer, is_converted, rgot);
|
||||||
buffer[0] = '\r';
|
} else if (!rgot)
|
||||||
rfd->pending_cr = 0;
|
return RKTIO_READ_EOF;
|
||||||
if (is_converted) is_converted[0] = 0;
|
else if (rfd->modes & RKTIO_OPEN_TEXT)
|
||||||
return 1;
|
return adjust_input_text(rfd, buffer, is_converted, rgot, offset);
|
||||||
} else
|
|
||||||
return 0;
|
|
||||||
} else
|
|
||||||
return RKTIO_READ_EOF;
|
|
||||||
} else if (rfd->modes & RKTIO_OPEN_TEXT)
|
|
||||||
return rktio_adjust_input_text(rfd, buffer, is_converted, rgot);
|
|
||||||
else
|
else
|
||||||
return rgot;
|
return rgot;
|
||||||
} else {
|
} else {
|
||||||
|
@ -849,24 +863,21 @@ RKTIO_EXTERN intptr_t rktio_buffered_byte_count(rktio_t *rktio, rktio_fd_t *fd)
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||||
return (fd->pending_cr ? 1 : 0);
|
return (fd->has_pending_byte ? 1 : 0);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||||
|
|
||||||
static intptr_t rktio_adjust_input_text(rktio_fd_t *rfd, char *buffer, char *is_converted, intptr_t got)
|
static intptr_t adjust_input_text(rktio_fd_t *rfd, char *buffer, char *is_converted,
|
||||||
|
intptr_t got, intptr_t offset)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
if (rfd->pending_cr) {
|
if (got && (buffer[got-1] == '\r') && !offset) {
|
||||||
memmove(buffer+1, buffer, got);
|
/* Save '\r' that might be followed by '\n' */
|
||||||
buffer[0] = '\r';
|
rfd->pending_byte = '\r';
|
||||||
rfd->pending_cr = 0;
|
rfd->has_pending_byte = 1;
|
||||||
got++;
|
|
||||||
}
|
|
||||||
if (got && (buffer[got-1] == '\r')) {
|
|
||||||
rfd->pending_cr = 1;
|
|
||||||
--got;
|
--got;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -888,6 +899,31 @@ static intptr_t rktio_adjust_input_text(rktio_fd_t *rfd, char *buffer, char *is_
|
||||||
return j;
|
return j;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static intptr_t adjust_input_text_for_pending_cr(rktio_fd_t *rfd, char *buffer, char *is_converted,
|
||||||
|
intptr_t got)
|
||||||
|
{
|
||||||
|
if (!got) {
|
||||||
|
/* There are no more bytes to decode. Report the final '\r' by itself */
|
||||||
|
buffer[0] = '\r';
|
||||||
|
rfd->has_pending_byte = 0;
|
||||||
|
if (is_converted) is_converted[0] = 0;
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
/* Combine the one new byte with a preceding '\r' */
|
||||||
|
if (buffer[0] == '\n') {
|
||||||
|
/* Decode */
|
||||||
|
rfd->has_pending_byte = 0;
|
||||||
|
if (is_converted) is_converted[0] = 1;
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
/* Save the new byte as pending while returning a '\r' by itself */
|
||||||
|
rfd->pending_byte = buffer[0];
|
||||||
|
buffer[0] = '\r';
|
||||||
|
if (is_converted) is_converted[0] = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void init_read_fd(rktio_t *rktio, rktio_fd_t *rfd)
|
static void init_read_fd(rktio_t *rktio, rktio_fd_t *rfd)
|
||||||
{
|
{
|
||||||
|
@ -1130,7 +1166,7 @@ intptr_t rktio_write(rktio_t *rktio, rktio_fd_t *rfd, const char *buffer, intptr
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (rfd->modes & RKTIO_OPEN_TEXT)
|
if (rfd->modes & RKTIO_OPEN_TEXT)
|
||||||
buffer = rktio_adjust_output_text(buffer, &towrite);
|
buffer = adjust_output_text(buffer, &towrite);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
ok = WriteFile((HANDLE)rfd->fd, buffer, towrite, &winwrote, NULL);
|
ok = WriteFile((HANDLE)rfd->fd, buffer, towrite, &winwrote, NULL);
|
||||||
|
@ -1152,12 +1188,14 @@ intptr_t rktio_write(rktio_t *rktio, rktio_fd_t *rfd, const char *buffer, intptr
|
||||||
|
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
get_windows_error();
|
get_windows_error();
|
||||||
|
if (buffer != orig_buffer)
|
||||||
|
free((char *)buffer);
|
||||||
return RKTIO_WRITE_ERROR;
|
return RKTIO_WRITE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buffer != orig_buffer) {
|
if (buffer != orig_buffer) {
|
||||||
/* Convert converted count back to original count: */
|
/* Convert converted count back to original count: */
|
||||||
winwrote = rktio_recount_output_text(orig_buffer, buffer, winwrote);
|
winwrote = recount_output_text(orig_buffer, buffer, winwrote);
|
||||||
free((char *)buffer);
|
free((char *)buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1363,7 +1401,7 @@ intptr_t rktio_write(rktio_t *rktio, rktio_fd_t *rfd, const char *buffer, intptr
|
||||||
|
|
||||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||||
|
|
||||||
static const char *rktio_adjust_output_text(const char *buffer, intptr_t *towrite)
|
static const char *adjust_output_text(const char *buffer, intptr_t *towrite)
|
||||||
{
|
{
|
||||||
intptr_t len = *towrite, i, j, newlines = 0;
|
intptr_t len = *towrite, i, j, newlines = 0;
|
||||||
char *new_buffer;
|
char *new_buffer;
|
||||||
|
@ -1396,12 +1434,12 @@ static const char *rktio_adjust_output_text(const char *buffer, intptr_t *towrit
|
||||||
return new_buffer;
|
return new_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
static intptr_t rktio_recount_output_text(const char *orig_buffer, const char *buffer, intptr_t wrote)
|
static intptr_t recount_output_text(const char *orig_buffer, const char *buffer, intptr_t wrote)
|
||||||
{
|
{
|
||||||
intptr_t i = 0, j = 0;
|
intptr_t i = 0, j = 0;
|
||||||
|
|
||||||
while (j < wrote) {
|
while (j < wrote) {
|
||||||
if (buffer[i] == '\n')
|
if (orig_buffer[i] == '\n')
|
||||||
j += 2;
|
j += 2;
|
||||||
else
|
else
|
||||||
j++;
|
j++;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user