msvcirt: Add a more accurate implementation of streambuf::pbackfail

Iván Matellanes matellanesivan at gmail.com
Wed Aug 19 12:04:20 CDT 2015


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 at streambuf@@UAEHH at Z */
-/* ?pbackfail at streambuf@@UEAAHH at 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 at streambuf@@UAEJJW4seek_dir at ios@@H at Z */
 /* ?seekoff at streambuf@@UEAAJJW4seek_dir at ios@@H at 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 at streambuf@@UAEHH at Z */
+/* ?pbackfail at streambuf@@UEAAHH at 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 at streambuf@@IAEXPAD0H at Z */
 /* ?setb at streambuf@@IEAAXPEAD0H at 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




More information about the wine-patches mailing list