[2/6] msvcirt: Implement istream::operator>> for characters.

Iván Matellanes matellanesivan at gmail.com
Mon Aug 1 05:40:39 CDT 2016


Signed-off-by: Iván Matellanes <matellanes.ivan at gmail.com>
---
 dlls/msvcirt/msvcirt.c       | 13 +++++++-
 dlls/msvcirt/tests/msvcirt.c | 73 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 85 insertions(+), 1 deletion(-)

diff --git a/dlls/msvcirt/msvcirt.c b/dlls/msvcirt/msvcirt.c
index 5d55b58..361285a 100644
--- a/dlls/msvcirt/msvcirt.c
+++ b/dlls/msvcirt/msvcirt.c
@@ -3490,7 +3490,18 @@ int __thiscall istream_getdouble(istream *this, char *str, int count)
 DEFINE_THISCALL_WRAPPER(istream_read_char, 8)
 istream* __thiscall istream_read_char(istream *this, char *ch)
 {
-    FIXME("(%p %p) stub\n", this, ch);
+    ios *base = istream_get_ios(this);
+    int ret;
+
+    TRACE("(%p %p)\n", this, ch);
+
+    if (istream_ipfx(this, 0)) {
+        if ((ret = streambuf_sbumpc(base->sb)) == EOF)
+            base->state |= IOSTATE_eofbit | IOSTATE_failbit;
+        else
+            *ch = ret;
+        istream_isfx(this);
+    }
     return this;
 }
 
diff --git a/dlls/msvcirt/tests/msvcirt.c b/dlls/msvcirt/tests/msvcirt.c
index a921b27..a706703 100644
--- a/dlls/msvcirt/tests/msvcirt.c
+++ b/dlls/msvcirt/tests/msvcirt.c
@@ -327,6 +327,7 @@ static int (*__thiscall p_istream_sync)(istream*);
 static streampos (*__thiscall p_istream_tellg)(istream*);
 static int (*__thiscall p_istream_getint)(istream*, char*);
 static int (*__thiscall p_istream_getdouble)(istream*, char*, int);
+static istream* (*__thiscall p_istream_read_char)(istream*, char*);
 
 /* Emulate a __thiscall */
 #ifdef __i386__
@@ -542,6 +543,7 @@ static BOOL init(void)
         SET(p_istream_tellg, "?tellg at istream@@QEAAJXZ");
         SET(p_istream_getint, "?getint at istream@@AEAAHPEAD at Z");
         SET(p_istream_getdouble, "?getdouble at istream@@AEAAHPEADH at Z");
+        SET(p_istream_read_char, "??5istream@@QEAAAEAV0 at AEAD@Z");
     } else {
         p_operator_new = (void*)GetProcAddress(msvcrt, "??2 at YAPAXI@Z");
         p_operator_delete = (void*)GetProcAddress(msvcrt, "??3 at YAXPAX@Z");
@@ -679,6 +681,7 @@ static BOOL init(void)
         SET(p_istream_tellg, "?tellg at istream@@QAEJXZ");
         SET(p_istream_getint, "?getint at istream@@AAEHPAD at Z");
         SET(p_istream_getdouble, "?getdouble at istream@@AAEHPADH at Z");
+        SET(p_istream_read_char, "??5istream@@QAEAAV0 at AAD@Z");
     }
     SET(p_ios_static_lock, "?x_lockc at ios@@0U_CRT_CRITICAL_SECTION@@A");
     SET(p_ios_lockc, "?lockc at ios@@KAXXZ");
@@ -4851,6 +4854,75 @@ static void test_istream_getdouble(void)
     call_func1(p_strstreambuf_dtor, &ssb);
 }
 
+static void test_istream_read(void)
+{
+    istream is, *pis;
+    strstreambuf ssb, *pssb;
+    int len, ret, i;
+
+    /* makes tables narrower */
+    const ios_io_state IOSTATE_faileof = IOSTATE_failbit|IOSTATE_eofbit;
+
+    char c, char_out[] = {-85, ' ', 'a', -50};
+    struct istream_read_test {
+        enum { type_chr } type;
+        const char *stream_content;
+        ios_flags flags;
+        int width;
+        int expected_val;
+        ios_io_state expected_state;
+        int expected_width;
+        int expected_offset;
+        BOOL broken;
+    } tests[] = {
+        /* char */
+        {type_chr, "",      FLAGS_skipws, 6, /* -85 */ 0, IOSTATE_faileof, 6, 0, FALSE},
+        {type_chr, "  ",    FLAGS_skipws, 6, /* -85 */ 0, IOSTATE_faileof, 6, 2, FALSE},
+        {type_chr, " abc ", 0,            6, /* ' ' */ 1, IOSTATE_goodbit, 6, 1, FALSE},
+        {type_chr, " abc ", FLAGS_skipws, 6, /* 'a' */ 2, IOSTATE_goodbit, 6, 2, FALSE},
+        {type_chr, " a",    FLAGS_skipws, 0, /* 'a' */ 2, IOSTATE_goodbit, 0, 2, FALSE},
+        {type_chr, "\xce",  0,            6, /* -50 */ 3, IOSTATE_goodbit, 6, 1, FALSE},
+    };
+
+    pssb = call_func2(p_strstreambuf_dynamic_ctor, &ssb, 64);
+    ok(pssb == &ssb, "wrong return, expected %p got %p\n", &ssb, pssb);
+    ret = (int) call_func1(p_streambuf_allocate, &ssb.base);
+    ok(ret == 1, "expected 1 got %d\n", ret);
+    pis = call_func3(p_istream_sb_ctor, &is, &ssb.base, TRUE);
+    ok(pis == &is, "wrong return, expected %p got %p\n", &is, pis);
+
+    for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
+        len = strlen(tests[i].stream_content);
+        is.base_ios.state = IOSTATE_goodbit;
+        is.base_ios.flags = tests[i].flags;
+        is.base_ios.width = tests[i].width;
+        ssb.base.eback = ssb.base.gptr = ssb.base.base;
+        ssb.base.egptr = ssb.base.base + len;
+        memcpy(ssb.base.base, tests[i].stream_content, len);
+
+        switch (tests[i].type) {
+        case type_chr:
+            c = -85;
+            pis = call_func2(p_istream_read_char, &is, &c);
+            ok(c == char_out[tests[i].expected_val], "Test %d: expected %d got %d\n", i,
+                char_out[tests[i].expected_val], c);
+            break;
+        }
+
+        ok(pis == &is, "Test %d: wrong return, expected %p got %p\n", i, &is, pis);
+        ok(is.base_ios.state == tests[i].expected_state || /* xp, 2k3 */ broken(tests[i].broken),
+            "Test %d: expected %d got %d\n", i, tests[i].expected_state, is.base_ios.state);
+        ok(is.base_ios.width == tests[i].expected_width, "Test %d: expected %d got %d\n", i,
+            tests[i].expected_width, is.base_ios.width);
+        ok(ssb.base.gptr == ssb.base.base + tests[i].expected_offset ||
+            /* xp, 2k3 */ broken(tests[i].broken), "Test %d: expected %p got %p\n", i,
+            ssb.base.base + tests[i].expected_offset, ssb.base.gptr);
+    }
+
+    call_func1(p_istream_vbase_dtor, &is);
+    call_func1(p_strstreambuf_dtor, &ssb);
+}
+
 START_TEST(msvcirt)
 {
     if(!init())
@@ -4866,6 +4938,7 @@ START_TEST(msvcirt)
     test_istream();
     test_istream_getint();
     test_istream_getdouble();
+    test_istream_read();
 
     FreeLibrary(msvcrt);
     FreeLibrary(msvcirt);
-- 
2.7.4




More information about the wine-patches mailing list