=?UTF-8?Q?Iv=C3=A1n=20Matellanes=20?=: msvcirt: Implement stdiobuf:: underflow.

Alexandre Julliard julliard at wine.codeweavers.com
Wed Oct 7 10:00:47 CDT 2015


Module: wine
Branch: master
Commit: 775461912819a69578ac31c7950eff718a64cd31
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=775461912819a69578ac31c7950eff718a64cd31

Author: Iván Matellanes <matellanesivan at gmail.com>
Date:   Fri Oct  2 15:03:22 2015 +0200

msvcirt: Implement stdiobuf::underflow.

Signed-off-by: Iván Matellanes <matellanesivan at gmail.com>
Signed-off-by: Piotr Caban <piotr at codeweavers.com>

---

 dlls/msvcirt/msvcirt.c       | 25 +++++++++++++++++++++--
 dlls/msvcirt/tests/msvcirt.c | 47 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 70 insertions(+), 2 deletions(-)

diff --git a/dlls/msvcirt/msvcirt.c b/dlls/msvcirt/msvcirt.c
index 81519d0..2b54f5b 100644
--- a/dlls/msvcirt/msvcirt.c
+++ b/dlls/msvcirt/msvcirt.c
@@ -1607,8 +1607,29 @@ int __thiscall stdiobuf_sync(stdiobuf *this)
 DEFINE_THISCALL_WRAPPER(stdiobuf_underflow, 4)
 int __thiscall stdiobuf_underflow(stdiobuf *this)
 {
-    FIXME("(%p) stub\n", this);
-    return EOF;
+    TRACE("(%p)\n", this);
+    if (!this->file)
+        return EOF;
+    if (this->base.unbuffered)
+        return fgetc(this->file);
+    if (streambuf_allocate(&this->base) == EOF)
+        return EOF;
+
+    if (!this->base.egptr) {
+        /* set the get area to the first half of the buffer */
+        char *middle = this->base.base + (this->base.ebuf - this->base.base) / 2;
+        streambuf_setg(&this->base, this->base.base, middle, middle);
+    }
+    if (this->base.gptr >= this->base.egptr) {
+        /* read characters from the file */
+        int buffer_size = this->base.egptr - this->base.eback, read_bytes;
+        if (!this->base.eback ||
+            (read_bytes = fread(this->base.eback, sizeof(char), buffer_size, this->file)) <= 0)
+            return EOF;
+        memmove(this->base.egptr - read_bytes, this->base.eback, read_bytes);
+        this->base.gptr = this->base.egptr - 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 53af65c..1f85186 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_underflow)(stdiobuf*);
 
 /* ios */
 static ios* (*__thiscall p_ios_copy_ctor)(ios*, const ios*);
@@ -372,6 +373,7 @@ static BOOL init(void)
         SET(p_stdiobuf_file_ctor, "??0stdiobuf@@QEAA at PEAU_iobuf@@@Z");
         SET(p_stdiobuf_dtor, "??1stdiobuf@@UEAA at XZ");
         SET(p_stdiobuf_overflow, "?overflow at stdiobuf@@UEAAHH at Z");
+        SET(p_stdiobuf_underflow, "?underflow at stdiobuf@@UEAAHXZ");
 
         SET(p_ios_copy_ctor, "??0ios@@IEAA at AEBV0@@Z");
         SET(p_ios_ctor, "??0ios@@IEAA at XZ");
@@ -454,6 +456,7 @@ static BOOL init(void)
         SET(p_stdiobuf_file_ctor, "??0stdiobuf@@QAE at PAU_iobuf@@@Z");
         SET(p_stdiobuf_dtor, "??1stdiobuf@@UAE at XZ");
         SET(p_stdiobuf_overflow, "?overflow at stdiobuf@@UAEHH at Z");
+        SET(p_stdiobuf_underflow, "?underflow at stdiobuf@@UAEHXZ");
 
         SET(p_ios_copy_ctor, "??0ios@@IAE at ABV0@@Z");
         SET(p_ios_ctor, "??0ios@@IAE at XZ");
@@ -1913,6 +1916,50 @@ static void test_stdiobuf(void)
     stb2.base.epptr = buffer + 64;
     stb2.base.unbuffered = 1;
 
+    /* underflow */
+    ret = (int) call_func1(p_stdiobuf_underflow, &stb1);
+    ok(ret == 'N', "expected 'N' got %d\n", ret);
+    stb1.base.unbuffered = 0;
+    ret = (int) call_func1(p_stdiobuf_underflow, &stb1);
+    ok(ret == 'e', "expected 'e' got %d\n", ret);
+    ok(stb1.base.eback == stb1.base.base, "wrong get base, expected %p got %p\n", stb1.base.base, stb1.base.eback);
+    ok(stb1.base.gptr == stb1.base.egptr - 47, "wrong get pointer, expected %p got %p\n", stb1.base.egptr - 47, stb1.base.gptr);
+    ok(stb1.base.egptr == stb1.base.base + 256, "wrong get end, expected %p got %p\n", stb1.base.base + 256, stb1.base.egptr);
+    ok(*stb1.base.gptr == 'v', "expected 'v' got '%c'\n", *stb1.base.gptr);
+    stb1.base.pbase = stb1.base.pptr = stb1.base.epptr = NULL;
+    ret = (int) call_func1(p_stdiobuf_underflow, &stb1);
+    ok(ret == 'v', "expected 'v' got %d\n", ret);
+    ok(stb1.base.gptr == stb1.base.egptr - 46, "wrong get pointer, expected %p got %p\n", stb1.base.egptr - 46, stb1.base.gptr);
+    stb1.base.gptr = stb1.base.egptr;
+    ret = (int) call_func1(p_stdiobuf_underflow, &stb1);
+    ok(ret == EOF, "expected EOF got %d\n", ret);
+    stb1.base.unbuffered = 1;
+    ret = (int) call_func1(p_stdiobuf_underflow, &stb1);
+    ok(ret == EOF, "expected EOF got %d\n", ret);
+    rewind(stb2.file);
+    ret = (int) call_func1(p_stdiobuf_underflow, &stb2);
+    ok(ret == 'a', "expected 'a' got %d\n", ret);
+    stb2.base.unbuffered = 0;
+    stb2.base.eback = stb2.base.gptr = buffer + 16;
+    stb2.base.egptr = buffer + 32;
+    strcpy(buffer + 16, "and desert you");
+    ret = (int) call_func1(p_stdiobuf_underflow, &stb2);
+    ok(ret == 'a', "expected 'a' got %d\n", ret);
+    ok(stb2.base.gptr == buffer + 17, "wrong get pointer, expected %p got %p\n", buffer + 17, stb2.base.gptr);
+    stb2.base.eback = buffer;
+    stb2.base.gptr = stb2.base.egptr;
+    stb2.base.pbase = stb2.base.pptr = stb2.base.epptr = NULL;
+    ret = (int) call_func1(p_stdiobuf_underflow, &stb2);
+    ok(ret == 'N', "expected 'N' got %d\n", ret);
+    ok(stb2.base.gptr == stb2.base.egptr - 22, "wrong get pointer, expected %p got %p\n", stb2.base.egptr - 22, stb2.base.gptr);
+    ok(ftell(stb2.file) == 24, "ftell failed\n");
+    stb2.base.gptr = stb2.base.egptr;
+    ret = (int) call_func1(p_stdiobuf_underflow, &stb2);
+    ok(ret == EOF, "expected EOF got %d\n", ret);
+    stb2.base.unbuffered = 1;
+    ret = (int) call_func1(p_stdiobuf_underflow, &stb2);
+    ok(ret == EOF, "expected EOF got %d\n", ret);
+
     call_func1(p_stdiobuf_dtor, &stb1);
     call_func1(p_stdiobuf_dtor, &stb2);
     fclose(file1);




More information about the wine-cvs mailing list