From: Iván Matellanes Subject: msvcirt: Add a more accurate implementation of streambuf::pbackfail Message-Id: <55D4B714.4080804@gmail.com> Date: Wed, 19 Aug 2015 19:04:20 +0200 I found unexpected that no alternative implementation of pbackfail is provided by filebuf, so I double checked and it seems that streambuf::pbackfail does something more. It should be further tested when strstreambuf is implemented. --- dlls/msvcirt/msvcirt.c | 26 ++++++++++++++------------ dlls/msvcirt/tests/msvcirt.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 12 deletions(-) diff --git a/dlls/msvcirt/msvcirt.c b/dlls/msvcirt/msvcirt.c index ff31e8c..14fb05a 100644 --- a/dlls/msvcirt/msvcirt.c +++ b/dlls/msvcirt/msvcirt.c @@ -458,18 +458,6 @@ int __thiscall streambuf_overflow(streambuf *this, int c) return EOF; } -/* ?pbackfail@streambuf@@UAEHH@Z */ -/* ?pbackfail@streambuf@@UEAAHH@Z */ -DEFINE_THISCALL_WRAPPER(streambuf_pbackfail, 8) -#define call_streambuf_pbackfail(this, c) CALL_VTBL_FUNC(this, 36, int, (streambuf*, int), (this, c)) -int __thiscall streambuf_pbackfail(streambuf *this, int c) -{ - TRACE("(%p %d)\n", this, c); - if (this->gptr <= this->eback) - return EOF; - return *--this->gptr = c; -} - /* ?seekoff@streambuf@@UAEJJW4seek_dir@ios@@H@Z */ /* ?seekoff@streambuf@@UEAAJJW4seek_dir@ios@@H@Z */ DEFINE_THISCALL_WRAPPER(streambuf_seekoff, 16) @@ -489,6 +477,20 @@ streampos __thiscall streambuf_seekpos(streambuf *this, streampos pos, int mode) return call_streambuf_seekoff(this, pos, SEEKDIR_beg, mode); } +/* ?pbackfail@streambuf@@UAEHH@Z */ +/* ?pbackfail@streambuf@@UEAAHH@Z */ +DEFINE_THISCALL_WRAPPER(streambuf_pbackfail, 8) +#define call_streambuf_pbackfail(this, c) CALL_VTBL_FUNC(this, 36, int, (streambuf*, int), (this, c)) +int __thiscall streambuf_pbackfail(streambuf *this, int c) +{ + TRACE("(%p %d)\n", this, c); + if (this->gptr > this->eback) + return *--this->gptr = c; + if (call_streambuf_seekoff(this, -1, SEEKDIR_cur, OPENMODE_in) == EOF) + return EOF; + return c; +} + /* ?setb@streambuf@@IAEXPAD0H@Z */ /* ?setb@streambuf@@IEAAXPEAD0H@Z */ DEFINE_THISCALL_WRAPPER(streambuf_setb, 16) diff --git a/dlls/msvcirt/tests/msvcirt.c b/dlls/msvcirt/tests/msvcirt.c index b381b30..77ee0a8 100644 --- a/dlls/msvcirt/tests/msvcirt.c +++ b/dlls/msvcirt/tests/msvcirt.c @@ -1345,6 +1345,38 @@ static void test_filebuf(void) ret = (int) call_func4(p_filebuf_seekoff, &fb1, 16, SEEKDIR_beg, 0); ok(ret == 16, "wrong return, expected 16 got %d\n", ret); + /* pbackfail */ + ret = (int) call_func2(p_streambuf_pbackfail, &fb1.base, 'B'); + ok(ret == 'B', "wrong return, expected 'B' got %d\n", ret); + ok(fb1.base.gptr == NULL, "wrong get pointer, expected %p got %p\n", NULL, fb1.base.gptr); + ok(fb1.base.pptr == NULL, "wrong put pointer, expected %p got %p\n", NULL, fb1.base.pptr); + ok(_tell(fb1.fd) == 15, "_tell failed\n"); + fb1.base.eback = fb1.base.gptr = fb1.base.base; + fb1.base.egptr = fb1.base.pbase = fb1.base.pptr = fb1.base.base + 256; + fb1.base.epptr = fb1.base.ebuf; + ret = (int) call_func2(p_streambuf_pbackfail, &fb1.base, 'C'); + ok(ret == EOF, "wrong return, expected EOF got %d\n", ret); + ok(fb1.base.gptr == fb1.base.base, "wrong get pointer, expected %p got %p\n", fb1.base.base, fb1.base.gptr); + ok(fb1.base.pptr == NULL, "wrong put pointer, expected %p got %p\n", NULL, fb1.base.pptr); + ok(_tell(fb1.fd) == 15, "_tell failed\n"); + fb1.base.eback = fb1.base.gptr = fb1.base.base; + fb1.base.egptr = fb1.base.base + 2; + ret = (int) call_func2(p_streambuf_pbackfail, &fb1.base, 'C'); + ok(ret == 'C', "wrong return, expected 'C' got %d\n", ret); + ok(fb1.base.gptr == NULL, "wrong get pointer, expected %p got %p\n", NULL, fb1.base.gptr); + ok(fb1.base.pptr == NULL, "wrong put pointer, expected %p got %p\n", NULL, fb1.base.pptr); + ok(_tell(fb1.fd) == 12, "_tell failed\n"); + fb1.base.eback = fb1.base.gptr = fb1.base.base; + fb1.base.egptr = fb1.base.ebuf; + *fb1.base.gptr++ = 'D'; + ret = (int) call_func2(p_streambuf_pbackfail, &fb1.base, 'C'); + ok(ret == 'C', "wrong return, expected 'C' got %d\n", ret); + ok(fb1.base.gptr == fb1.base.base, "wrong get pointer, expected %p got %p\n", fb1.base.base, fb1.base.gptr); + ok(*fb1.base.gptr == 'C', "wrong character, expected 'C' got '%c'\n", *fb1.base.gptr); + ok(fb1.base.pptr == NULL, "wrong put pointer, expected %p got %p\n", NULL, fb1.base.pptr); + ok(_tell(fb1.fd) == 12, "_tell failed\n"); + fb1.base.eback = fb1.base.gptr = fb1.base.egptr = NULL; + /* close */ pret = (filebuf*) call_func1(p_filebuf_close, &fb2); ok(pret == NULL, "wrong return, expected %p got %p\n", NULL, pret); -- 2.1.4