Piotr Caban : msvcrt: Avoid allocations in _write implementation.
Alexandre Julliard
julliard at winehq.org
Wed Aug 5 16:05:00 CDT 2020
Module: wine
Branch: master
Commit: e0555a742f4e9527b31bd67a8dcf572046f7c4a8
URL: https://source.winehq.org/git/wine.git/?a=commit;h=e0555a742f4e9527b31bd67a8dcf572046f7c4a8
Author: Piotr Caban <piotr at codeweavers.com>
Date: Wed Aug 5 15:07:27 2020 +0200
msvcrt: Avoid allocations in _write implementation.
Signed-off-by: Piotr Caban <piotr at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/msvcrt/file.c | 154 +++++++++++++++--------------------------------------
1 file changed, 42 insertions(+), 112 deletions(-)
diff --git a/dlls/msvcrt/file.c b/dlls/msvcrt/file.c
index e63cedede5..b6655e6886 100644
--- a/dlls/msvcrt/file.c
+++ b/dlls/msvcrt/file.c
@@ -3443,15 +3443,10 @@ int CDECL _wutime(const MSVCRT_wchar_t* path, struct MSVCRT___utimbuf32 *t)
*/
int CDECL MSVCRT__write(int fd, const void* buf, unsigned int count)
{
- DWORD num_written;
ioinfo *info = get_ioinfo(fd);
HANDLE hand = info->handle;
+ DWORD num_written, i;
- /* Don't trace small writes, it gets *very* annoying */
-#if 0
- if (count > 32)
- TRACE(":fd (%d) handle (%d) buf (%p) len (%d)\n",fd,hand,buf,count);
-#endif
if (hand == INVALID_HANDLE_VALUE || fd == MSVCRT_NO_CONSOLE_FD)
{
*MSVCRT__errno() = MSVCRT_EBADF;
@@ -3472,148 +3467,83 @@ int CDECL MSVCRT__write(int fd, const void* buf, unsigned int count)
if (!(info->wxflag & WX_TEXT))
{
- if (WriteFile(hand, buf, count, &num_written, NULL)
- && (num_written == count))
+ if (!WriteFile(hand, buf, count, &num_written, NULL)
+ || num_written != count)
{
- release_ioinfo(info);
- return num_written;
+ TRACE("WriteFile (fd %d, hand %p) failed-last error (%d)\n", fd,
+ hand, GetLastError());
+ msvcrt_set_errno(GetLastError());
+ num_written = -1;
}
- TRACE("WriteFile (fd %d, hand %p) failed-last error (%d)\n", fd,
- hand, GetLastError());
- msvcrt_set_errno(GetLastError());
+
+ release_ioinfo(info);
+ return num_written;
}
- else
+
+ for (i = 0; i < count;)
{
- unsigned int i, j, nr_lf, size;
- char *p = NULL;
- const char *q;
const char *s = buf;
+ char lfbuf[2048];
+ DWORD j;
if (!(info->exflag & (EF_UTF8|EF_UTF16)))
{
- /* find number of \n */
- for (nr_lf=0, i=0; i<count; i++)
- if (s[i] == '\n')
- nr_lf++;
- if (nr_lf)
- {
- size = count+nr_lf;
- if ((q = p = MSVCRT_malloc(size)))
- {
- for (s = buf, i = 0, j = 0; i < count; i++)
- {
- if (s[i] == '\n')
- p[j++] = '\r';
- p[j++] = s[i];
- }
- }
- else
- {
- FIXME("Malloc failed\n");
- nr_lf = 0;
- size = count;
- q = buf;
- }
- }
- else
+ for (j = 0; i < count && j < sizeof(lfbuf)-1; i++, j++)
{
- size = count;
- q = buf;
+ if (s[i] == '\n')
+ lfbuf[j++] = '\r';
+ lfbuf[j] = s[i];
}
}
else if (info->exflag & EF_UTF16)
{
- for (nr_lf=0, i=0; i<count; i+=2)
- if (s[i]=='\n' && s[i+1]==0)
- nr_lf += 2;
- if (nr_lf)
+ for (j = 0; i < count && j < sizeof(lfbuf)-3; i++, j++)
{
- size = count+nr_lf;
- if ((q = p = MSVCRT_malloc(size)))
- {
- for (s=buf, i=0, j=0; i<count; i++)
- {
- if (s[i]=='\n' && s[i+1]==0)
- {
- p[j++] = '\r';
- p[j++] = 0;
- }
- p[j++] = s[i++];
- p[j++] = s[i];
- }
- }
- else
+ if (s[i] == '\n' && !s[i+1])
{
- FIXME("Malloc failed\n");
- nr_lf = 0;
- size = count;
- q = buf;
+ lfbuf[j++] = '\r';
+ lfbuf[j++] = 0;
}
- }
- else
- {
- size = count;
- q = buf;
+ lfbuf[j++] = s[i++];
+ lfbuf[j] = s[i];
}
}
else
{
- DWORD conv_len;
-
- for(nr_lf=0, i=0; i<count; i+=2)
- if (s[i]=='\n' && s[i+1]==0)
- nr_lf++;
-
- conv_len = WideCharToMultiByte(CP_UTF8, 0, (WCHAR*)buf, count/2, NULL, 0, NULL, NULL);
- if(!conv_len) {
- msvcrt_set_errno(GetLastError());
- MSVCRT_free(p);
- release_ioinfo(info);
- return -1;
- }
+ char conv[sizeof(lfbuf)/4];
- size = conv_len+nr_lf;
- if((p = MSVCRT_malloc(count+nr_lf*2+size)))
+ for (j = 0; i < count && j < sizeof(conv)-3; i++, j++)
{
- for (s=buf, i=0, j=0; i<count; i++)
+ if (s[i] == '\n' && !s[i+1])
{
- if (s[i]=='\n' && s[i+1]==0)
- {
- p[j++] = '\r';
- p[j++] = 0;
- }
- p[j++] = s[i++];
- p[j++] = s[i];
+ conv[j++] = '\r';
+ conv[j++] = 0;
}
- q = p+count+nr_lf*2;
- WideCharToMultiByte(CP_UTF8, 0, (WCHAR*)p, count/2+nr_lf,
- p+count+nr_lf*2, conv_len+nr_lf, NULL, NULL);
+ conv[j++] = s[i++];
+ conv[j] = s[i];
}
- else
+
+ j = WideCharToMultiByte(CP_UTF8, 0, (WCHAR*)conv, j/2, lfbuf, sizeof(lfbuf), NULL, NULL);
+ if (!j)
{
- FIXME("Malloc failed\n");
- nr_lf = 0;
- size = count;
- q = buf;
+ msvcrt_set_errno(GetLastError());
+ release_ioinfo(info);
+ return -1;
}
}
- if (!WriteFile(hand, q, size, &num_written, NULL))
- num_written = -1;
- release_ioinfo(info);
- MSVCRT_free(p);
- if (num_written != size)
+ if (!WriteFile(hand, lfbuf, j, &num_written, NULL) || num_written != j)
{
- TRACE("WriteFile (fd %d, hand %p) failed-last error (%d), num_written %d\n",
- fd, hand, GetLastError(), num_written);
+ TRACE("WriteFile (fd %d, hand %p) failed-last error (%d)\n", fd,
+ hand, GetLastError());
msvcrt_set_errno(GetLastError());
+ release_ioinfo(info);
return -1;
}
- return count;
}
release_ioinfo(info);
- return -1;
+ return count;
}
/*********************************************************************
More information about the wine-cvs
mailing list