[6/7] msvcirt: Implement filebuf::underflow

Iván Matellanes matellanesivan at gmail.com
Mon Aug 10 13:09:26 CDT 2015


---
 dlls/msvcirt/msvcirt.c       | 21 +++++++++++++++++++--
 dlls/msvcirt/tests/msvcirt.c | 39 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 58 insertions(+), 2 deletions(-)

diff --git a/dlls/msvcirt/msvcirt.c b/dlls/msvcirt/msvcirt.c
index 1eb04cb..580af82 100644
--- a/dlls/msvcirt/msvcirt.c
+++ b/dlls/msvcirt/msvcirt.c
@@ -1088,8 +1088,25 @@ int __thiscall filebuf_sync(filebuf *this)
 DEFINE_THISCALL_WRAPPER(filebuf_underflow, 4)
 int __thiscall filebuf_underflow(filebuf *this)
 {
-    FIXME("(%p) stub\n", this);
-    return EOF;
+    int buffer_size, read_bytes;
+    char c;
+
+    TRACE("(%p)\n", this);
+
+    if (this->base.unbuffered)
+        return (_read(this->fd, &c, 1) < 1) ? EOF : c;
+
+    if (this->base.gptr >= this->base.egptr) {
+        if (call_streambuf_sync(&this->base) == EOF)
+            return EOF;
+        buffer_size = this->base.ebuf - this->base.base;
+        read_bytes = _read(this->fd, this->base.base, buffer_size);
+        if (read_bytes <= 0)
+            return EOF;
+        this->base.eback = this->base.gptr = this->base.base;
+        this->base.egptr = this->base.base + read_bytes;
+    }
+    return *this->base.gptr;
 }
 
 /* ??0ios@@IAE at ABV0@@Z */
diff --git a/dlls/msvcirt/tests/msvcirt.c b/dlls/msvcirt/tests/msvcirt.c
index 1059e3a..de53889 100644
--- a/dlls/msvcirt/tests/msvcirt.c
+++ b/dlls/msvcirt/tests/msvcirt.c
@@ -161,6 +161,7 @@ static int (*__thiscall p_filebuf_setmode)(filebuf*, int);
 static streambuf* (*__thiscall p_filebuf_setbuf)(filebuf*, char*, int);
 static int (*__thiscall p_filebuf_sync)(filebuf*);
 static int (*__thiscall p_filebuf_overflow)(filebuf*, int);
+static int (*__thiscall p_filebuf_underflow)(filebuf*);
 
 /* ios */
 static ios* (*__thiscall p_ios_copy_ctor)(ios*, const ios*);
@@ -303,6 +304,7 @@ static BOOL init(void)
         SET(p_filebuf_setbuf, "?setbuf at filebuf@@UEAAPEAVstreambuf@@PEADH at Z");
         SET(p_filebuf_sync, "?sync at filebuf@@UEAAHXZ");
         SET(p_filebuf_overflow, "?overflow at filebuf@@UEAAHH at Z");
+        SET(p_filebuf_underflow, "?underflow at filebuf@@UEAAHXZ");
 
         SET(p_ios_copy_ctor, "??0ios@@IEAA at AEBV0@@Z");
         SET(p_ios_ctor, "??0ios@@IEAA at XZ");
@@ -365,6 +367,7 @@ static BOOL init(void)
         SET(p_filebuf_setbuf, "?setbuf at filebuf@@UAEPAVstreambuf@@PADH at Z");
         SET(p_filebuf_sync, "?sync at filebuf@@UAEHXZ");
         SET(p_filebuf_overflow, "?overflow at filebuf@@UAEHH at Z");
+        SET(p_filebuf_underflow, "?underflow at filebuf@@UAEHXZ");
 
         SET(p_ios_copy_ctor, "??0ios@@IAE at ABV0@@Z");
         SET(p_ios_ctor, "??0ios@@IAE at XZ");
@@ -1261,10 +1264,46 @@ static void test_filebuf(void)
     fb2.base.do_lock = -1;
     ret = (int) call_func2(p_filebuf_overflow, &fb2, EOF);
     ok(ret == 1, "wrong return, expected 1 got %d\n", ret);
+
+    /* underflow */
+    ret = (int) call_func1(p_filebuf_underflow, &fb1);
+    ok(ret == EOF, "wrong return, expected EOF 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);
+    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;
+    *fb1.base.gptr = 'A';
+    ret = (int) call_func1(p_filebuf_underflow, &fb1);
+    ok(ret == 'A', "wrong return, expected 'A' 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 == fb1.base.base + 256, "wrong put pointer, expected %p got %p\n", fb1.base.base + 256, fb1.base.pptr);
+    fb1.base.gptr = fb1.base.ebuf;
+    ret = (int) call_func1(p_filebuf_underflow, &fb1);
+    ok(ret == EOF, "wrong return, expected EOF 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(_lseek(fb1.fd, 0, SEEK_SET) == 0, "_lseek failed\n");
+    ret = (int) call_func1(p_filebuf_underflow, &fb1);
+    ok(ret == 'f', "wrong return, expected 'f' got %d\n", ret);
+    ok(fb1.base.eback == fb1.base.base, "wrong get base, expected %p got %p\n", fb1.base.base, fb1.base.eback);
+    ok(fb1.base.gptr == fb1.base.base, "wrong get pointer, expected %p got %p\n", fb1.base.base, fb1.base.gptr);
+    ok(fb1.base.egptr == fb1.base.base + 106, "wrong get end pointer, expected %p got %p\n", fb1.base.base + 106, fb1.base.egptr);
+    ok(fb1.base.pptr == NULL, "wrong put pointer, expected %p got %p\n", NULL, fb1.base.pptr);
+    ret = (int) call_func1(p_filebuf_underflow, &fb2);
+    ok(ret == EOF, "wrong return, expected EOF got %d\n", ret);
+    ok(_write(fb2.fd, "A\n", 2) == 2, "_write failed\n");
+    ok(_lseek(fb2.fd, 0, SEEK_SET) == 0, "_lseek failed\n");
+    ret = (int) call_func1(p_filebuf_underflow, &fb2);
+    ok(ret == 'A', "wrong return, expected 'A' got %d\n", ret);
+    ret = (int) call_func1(p_filebuf_underflow, &fb2);
+    ok(ret == '\n', "wrong return, expected '\\n' got %d\n", ret);
     fb2.base.do_lock = 0;
     pret = (filebuf*) call_func1(p_filebuf_close, &fb2);
     ok(pret == &fb2, "wrong return, expected %p got %p\n", &fb2, pret);
     fb2.base.do_lock = -1;
+    ret = (int) call_func1(p_filebuf_underflow, &fb2);
+    ok(ret == EOF, "wrong return, expected EOF got %d\n", ret);
 
     /* close */
     pret = (filebuf*) call_func1(p_filebuf_close, &fb2);
-- 
2.1.4




More information about the wine-patches mailing list