Module: wine Branch: master Commit: c16e4f5cc52f5b9a6f8e99b9d76fd565bd2a9d79 URL: http://source.winehq.org/git/wine.git/?a=commit;h=c16e4f5cc52f5b9a6f8e99b9d7...
Author: Iván Matellanes matellanesivan@gmail.com Date: Fri Oct 2 15:03:23 2015 +0200
msvcirt: Implement stdiobuf::sync.
Signed-off-by: Iván Matellanes matellanesivan@gmail.com Signed-off-by: Piotr Caban piotr@codeweavers.com
---
dlls/msvcirt/msvcirt.c | 27 +++++++++++++++++++-- dlls/msvcirt/tests/msvcirt.c | 56 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 2 deletions(-)
diff --git a/dlls/msvcirt/msvcirt.c b/dlls/msvcirt/msvcirt.c index 2b54f5b..602ab77 100644 --- a/dlls/msvcirt/msvcirt.c +++ b/dlls/msvcirt/msvcirt.c @@ -1598,8 +1598,31 @@ FILE* __thiscall stdiobuf_stdiofile(stdiobuf *this) DEFINE_THISCALL_WRAPPER(stdiobuf_sync, 4) int __thiscall stdiobuf_sync(stdiobuf *this) { - FIXME("(%p) stub\n", this); - return EOF; + TRACE("(%p)\n", this); + if (this->base.unbuffered) + return 0; + /* flush the put area */ + if (call_streambuf_overflow(&this->base, EOF) == EOF) + return EOF; + /* flush the get area */ + if (this->base.gptr < this->base.egptr) { + char *ptr; + int fd, mode, offset = this->base.egptr - this->base.gptr; + if ((fd = fileno(this->file)) < 0) + return EOF; + mode = _setmode(fd, _O_TEXT); + _setmode(fd, mode); + if (mode & _O_TEXT) { + /* in text mode, '\n' in the buffer means '\r\n' in the file */ + for (ptr = this->base.gptr; ptr < this->base.egptr; ptr++) + if (*ptr == '\n') + offset++; + } + if (fseek(this->file, -offset, SEEK_CUR)) + return EOF; + this->base.gptr = this->base.egptr; + } + return 0; }
/* ?underflow@stdiobuf@@UAEHXZ */ diff --git a/dlls/msvcirt/tests/msvcirt.c b/dlls/msvcirt/tests/msvcirt.c index 1f85186..8bc45c1 100644 --- a/dlls/msvcirt/tests/msvcirt.c +++ b/dlls/msvcirt/tests/msvcirt.c @@ -210,6 +210,7 @@ static int (*__thiscall p_strstreambuf_underflow)(strstreambuf*); static stdiobuf* (*__thiscall p_stdiobuf_file_ctor)(stdiobuf*, FILE*); static void (*__thiscall p_stdiobuf_dtor)(stdiobuf*); static int (*__thiscall p_stdiobuf_overflow)(stdiobuf*, int); +static int (*__thiscall p_stdiobuf_sync)(stdiobuf*); static int (*__thiscall p_stdiobuf_underflow)(stdiobuf*);
/* ios */ @@ -373,6 +374,7 @@ static BOOL init(void) SET(p_stdiobuf_file_ctor, "??0stdiobuf@@QEAA@PEAU_iobuf@@@Z"); SET(p_stdiobuf_dtor, "??1stdiobuf@@UEAA@XZ"); SET(p_stdiobuf_overflow, "?overflow@stdiobuf@@UEAAHH@Z"); + SET(p_stdiobuf_sync, "?sync@stdiobuf@@UEAAHXZ"); SET(p_stdiobuf_underflow, "?underflow@stdiobuf@@UEAAHXZ");
SET(p_ios_copy_ctor, "??0ios@@IEAA@AEBV0@@Z"); @@ -456,6 +458,7 @@ static BOOL init(void) SET(p_stdiobuf_file_ctor, "??0stdiobuf@@QAE@PAU_iobuf@@@Z"); SET(p_stdiobuf_dtor, "??1stdiobuf@@UAE@XZ"); SET(p_stdiobuf_overflow, "?overflow@stdiobuf@@UAEHH@Z"); + SET(p_stdiobuf_sync, "?sync@stdiobuf@@UAEHXZ"); SET(p_stdiobuf_underflow, "?underflow@stdiobuf@@UAEHXZ");
SET(p_ios_copy_ctor, "??0ios@@IAE@ABV0@@Z"); @@ -1960,6 +1963,59 @@ static void test_stdiobuf(void) ret = (int) call_func1(p_stdiobuf_underflow, &stb2); ok(ret == EOF, "expected EOF got %d\n", ret);
+ /* sync */ + ret = (int) call_func1(p_stdiobuf_sync, &stb1); + ok(ret == 0, "expected 0 got %d\n", ret); + stb1.base.gptr = stb1.base.eback; + ret = (int) call_func1(p_stdiobuf_sync, &stb1); + ok(ret == 0, "expected 0 got %d\n", ret); + stb1.base.unbuffered = 0; + ret = (int) call_func1(p_stdiobuf_sync, &stb1); + ok(ret == EOF, "expected EOF got %d\n", ret); + ok(stb1.base.pbase == stb1.base.base + 256, "wrong put base, expected %p got %p\n", stb1.base.base + 256, stb1.base.pbase); + ok(stb1.base.pptr == stb1.base.base + 256, "wrong put pointer, expected %p got %p\n", stb1.base.base + 256, stb1.base.pptr); + ok(stb1.base.epptr == stb1.base.base + 512, "wrong put end, expected %p got %p\n", stb1.base.base + 512, stb1.base.epptr); + stb1.base.gptr = stb1.base.egptr; + ret = (int) call_func1(p_stdiobuf_sync, &stb1); + ok(ret == 0, "expected 0 got %d\n", ret); + stb1.base.eback = stb1.base.gptr = stb1.base.egptr = NULL; + stb1.base.pptr = stb1.base.epptr; + ret = (int) call_func1(p_stdiobuf_sync, &stb1); + ok(ret == EOF, "expected EOF got %d\n", ret); + ok(stb1.base.gptr == NULL, "wrong get pointer, expected %p got %p\n", NULL, stb1.base.gptr); + stb1.base.pptr = stb1.base.pbase; + ret = (int) call_func1(p_stdiobuf_sync, &stb1); + ok(ret == 0, "expected 0 got %d\n", ret); + ok(stb1.base.gptr == NULL, "wrong get pointer, expected %p got %p\n", NULL, stb1.base.gptr); + stb1.base.unbuffered = 1; + stb2.base.unbuffered = 0; + stb2.base.egptr = stb2.base.ebuf; + ret = (int) call_func1(p_stdiobuf_sync, &stb2); + ok(ret == EOF, "expected EOF got %d\n", ret); + ok(stb2.base.pbase == stb2.base.base + 32, "wrong put base, expected %p got %p\n", stb2.base.base + 32, stb2.base.pbase); + ok(stb2.base.pptr == stb2.base.base + 32, "wrong put pointer, expected %p got %p\n", stb2.base.base + 32, stb2.base.pptr); + ok(stb2.base.epptr == stb2.base.base + 64, "wrong put end, expected %p got %p\n", stb2.base.base + 64, stb2.base.epptr); + stb2.base.egptr = stb2.base.pbase; + stb2.base.gptr = stb2.base.egptr - 25; + ret = (int) call_func1(p_stdiobuf_sync, &stb2); + ok(ret == EOF, "expected EOF got %d\n", ret); + ret = (int) call_func3(p_streambuf_xsputn, &stb2.base, "Never gonna make you cry", 24); + ok(ret == 24, "expected 24 got %d\n", ret); + ret = (int) call_func1(p_stdiobuf_sync, &stb2); + ok(ret == 0, "expected 0 got %d\n", ret); + ok(ftell(stb2.file) == 23, "ftell failed\n"); + ok(fseek(stb2.file, 3, SEEK_SET) == 0, "fseek failed\n"); + stb2.base.gptr = stb2.base.egptr - 3; + strcpy(stb2.base.gptr, "a\nc"); + ret = (int) call_func1(p_stdiobuf_sync, &stb2); + ok(ret == EOF, "expected EOF got %d\n", ret); + ok(stb2.base.gptr == stb2.base.egptr - 3, "wrong get pointer, expected %p got %p\n", stb2.base.egptr - 3, stb2.base.gptr); + *(stb2.base.gptr+1) = 'b'; + ret = (int) call_func1(p_stdiobuf_sync, &stb2); + ok(ret == 0, "expected 0 got %d\n", ret); + ok(stb2.base.gptr == stb2.base.egptr, "wrong get pointer, expected %p got %p\n", stb2.base.egptr, stb2.base.gptr); + stb2.base.unbuffered = 1; + call_func1(p_stdiobuf_dtor, &stb1); call_func1(p_stdiobuf_dtor, &stb2); fclose(file1);