[2/6] msvcirt: Implement istream constructors/destructors

Iván Matellanes matellanesivan at gmail.com
Fri Jul 15 04:26:52 CDT 2016


Signed-off-by: Iván Matellanes <matellanes.ivan at gmail.com>
---
 dlls/msvcirt/msvcirt.c       |  63 ++++++++++++--
 dlls/msvcirt/tests/msvcirt.c | 194 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 248 insertions(+), 9 deletions(-)

diff --git a/dlls/msvcirt/msvcirt.c b/dlls/msvcirt/msvcirt.c
index bf0967d..33d1b14 100644
--- a/dlls/msvcirt/msvcirt.c
+++ b/dlls/msvcirt/msvcirt.c
@@ -2898,7 +2898,22 @@ static inline istream* ios_to_istream(const ios *base)
 DEFINE_THISCALL_WRAPPER(istream_sb_ctor, 12)
 istream* __thiscall istream_sb_ctor(istream *this, streambuf *sb, BOOL virt_init)
 {
-    FIXME("(%p %p %d) stub\n", this, sb, virt_init);
+    ios *base;
+
+    TRACE("(%p %p %d)\n", this, sb, virt_init);
+
+    if (virt_init) {
+        this->vbtable = istream_vbtable;
+        base = istream_get_ios(this);
+        ios_sb_ctor(base, sb);
+    } else {
+        base = istream_get_ios(this);
+        ios_init(base, sb);
+    }
+    base->vtable = &MSVCP_istream_vtable;
+    base->flags |= FLAGS_skipws;
+    this->extract_delim = 0;
+    this->count = 0;
     return this;
 }
 
@@ -2907,8 +2922,7 @@ istream* __thiscall istream_sb_ctor(istream *this, streambuf *sb, BOOL virt_init
 DEFINE_THISCALL_WRAPPER(istream_copy_ctor, 12)
 istream* __thiscall istream_copy_ctor(istream *this, const istream *copy, BOOL virt_init)
 {
-    FIXME("(%p %p %d) stub\n", this, copy, virt_init);
-    return this;
+    return istream_sb_ctor(this, istream_get_ios(copy)->sb, virt_init);
 }
 
 /* ??0istream@@IAE at XZ */
@@ -2916,7 +2930,20 @@ istream* __thiscall istream_copy_ctor(istream *this, const istream *copy, BOOL v
 DEFINE_THISCALL_WRAPPER(istream_ctor, 8)
 istream* __thiscall istream_ctor(istream *this, BOOL virt_init)
 {
-    FIXME("(%p %d) stub\n", this, virt_init);
+    ios *base;
+
+    TRACE("(%p %d)\n", this, virt_init);
+
+    if (virt_init) {
+        this->vbtable = istream_vbtable;
+        base = istream_get_ios(this);
+        ios_ctor(base);
+    } else
+        base = istream_get_ios(this);
+    base->vtable = &MSVCP_istream_vtable;
+    base->flags |= FLAGS_skipws;
+    this->extract_delim = 0;
+    this->count = 0;
     return this;
 }
 
@@ -2925,7 +2952,9 @@ istream* __thiscall istream_ctor(istream *this, BOOL virt_init)
 DEFINE_THISCALL_WRAPPER(istream_dtor, 4)
 void __thiscall istream_dtor(ios *base)
 {
-    FIXME("(%p) stub\n", base);
+    istream *this = ios_to_istream(base);
+
+    TRACE("(%p)\n", this);
 }
 
 /* ??4istream@@IAEAAV0 at PAVstreambuf@@@Z */
@@ -2933,7 +2962,19 @@ void __thiscall istream_dtor(ios *base)
 DEFINE_THISCALL_WRAPPER(istream_assign_sb, 8)
 istream* __thiscall istream_assign_sb(istream *this, streambuf *sb)
 {
-    FIXME("(%p %p) stub\n", this, sb);
+    ios *base = istream_get_ios(this);
+
+    TRACE("(%p %p)\n", this, sb);
+
+    ios_init(base, sb);
+    base->state &= IOSTATE_badbit;
+    base->delbuf = 0;
+    base->tie = NULL;
+    base->flags = FLAGS_skipws;
+    base->precision = 6;
+    base->fill = ' ';
+    base->width = 0;
+    this->count = 0;
     return this;
 }
 
@@ -2942,8 +2983,7 @@ istream* __thiscall istream_assign_sb(istream *this, streambuf *sb)
 DEFINE_THISCALL_WRAPPER(istream_assign, 8)
 istream* __thiscall istream_assign(istream *this, const istream *rhs)
 {
-    FIXME("(%p %p) stub\n", this, rhs);
-    return this;
+    return istream_assign_sb(this, istream_get_ios(rhs)->sb);
 }
 
 /* ??_Distream@@QAEXXZ */
@@ -2951,7 +2991,12 @@ istream* __thiscall istream_assign(istream *this, const istream *rhs)
 DEFINE_THISCALL_WRAPPER(istream_vbase_dtor, 4)
 void __thiscall istream_vbase_dtor(istream *this)
 {
-    FIXME("(%p) stub\n", this);
+    ios *base = istream_to_ios(this);
+
+    TRACE("(%p)\n", this);
+
+    istream_dtor(base);
+    ios_dtor(base);
 }
 
 /* ??_Eistream@@UAEPAXI at Z */
diff --git a/dlls/msvcirt/tests/msvcirt.c b/dlls/msvcirt/tests/msvcirt.c
index 13b8397..bdbdbf0 100644
--- a/dlls/msvcirt/tests/msvcirt.c
+++ b/dlls/msvcirt/tests/msvcirt.c
@@ -146,6 +146,14 @@ typedef struct _ostream {
     ios base_ios; /* virtually inherited */
 } ostream;
 
+/* class istream */
+typedef struct {
+    const int *vbtable;
+    int extract_delim;
+    int count;
+    ios base_ios; /* virtually inherited */
+} istream;
+
 static inline float __port_infinity(void)
 {
     static const unsigned __inf_bytes = 0x7f800000;
@@ -293,6 +301,15 @@ static ostream* (*__thiscall p_ostream_print_double)(ostream*, double);
 static ostream* (*__thiscall p_ostream_print_ptr)(ostream*, const void*);
 static ostream* (*__thiscall p_ostream_print_streambuf)(ostream*, streambuf*);
 
+/* istream */
+static istream* (*__thiscall p_istream_copy_ctor)(istream*, const istream*, BOOL);
+static istream* (*__thiscall p_istream_ctor)(istream*, BOOL);
+static istream* (*__thiscall p_istream_sb_ctor)(istream*, streambuf*, BOOL);
+static void (*__thiscall p_istream_dtor)(ios*);
+static istream* (*__thiscall p_istream_assign_sb)(istream*, streambuf*);
+static istream* (*__thiscall p_istream_assign)(istream*, const istream*);
+static void (*__thiscall p_istream_vbase_dtor)(istream*);
+
 /* Emulate a __thiscall */
 #ifdef __i386__
 
@@ -481,6 +498,14 @@ static BOOL init(void)
         SET(p_ostream_print_double, "??6ostream@@QEAAAEAV0 at N@Z");
         SET(p_ostream_print_ptr, "??6ostream@@QEAAAEAV0 at PEBX@Z");
         SET(p_ostream_print_streambuf, "??6ostream@@QEAAAEAV0 at PEAVstreambuf@@@Z");
+
+        SET(p_istream_copy_ctor, "??0istream@@IEAA at AEBV0@@Z");
+        SET(p_istream_ctor, "??0istream@@IEAA at XZ");
+        SET(p_istream_sb_ctor, "??0istream@@QEAA at PEAVstreambuf@@@Z");
+        SET(p_istream_dtor, "??1istream@@UEAA at XZ");
+        SET(p_istream_assign_sb, "??4istream@@IEAAAEAV0 at PEAVstreambuf@@@Z");
+        SET(p_istream_assign, "??4istream@@IEAAAEAV0 at AEBV0@@Z");
+        SET(p_istream_vbase_dtor, "??_Distream@@QEAAXXZ");
     } else {
         p_operator_new = (void*)GetProcAddress(msvcrt, "??2 at YAPAXI@Z");
         p_operator_delete = (void*)GetProcAddress(msvcrt, "??3 at YAXPAX@Z");
@@ -592,6 +617,14 @@ static BOOL init(void)
         SET(p_ostream_print_double, "??6ostream@@QAEAAV0 at N@Z");
         SET(p_ostream_print_ptr, "??6ostream@@QAEAAV0 at PBX@Z");
         SET(p_ostream_print_streambuf, "??6ostream@@QAEAAV0 at PAVstreambuf@@@Z");
+
+        SET(p_istream_copy_ctor, "??0istream@@IAE at ABV0@@Z");
+        SET(p_istream_ctor, "??0istream@@IAE at XZ");
+        SET(p_istream_sb_ctor, "??0istream@@QAE at PAVstreambuf@@@Z");
+        SET(p_istream_dtor, "??1istream@@UAE at XZ");
+        SET(p_istream_assign_sb, "??4istream@@IAEAAV0 at PAVstreambuf@@@Z");
+        SET(p_istream_assign, "??4istream@@IAEAAV0 at ABV0@@Z");
+        SET(p_istream_vbase_dtor, "??_Distream@@QAEXXZ");
     }
     SET(p_ios_static_lock, "?x_lockc at ios@@0U_CRT_CRITICAL_SECTION@@A");
     SET(p_ios_lockc, "?lockc at ios@@KAXXZ");
@@ -3371,6 +3404,166 @@ static void test_ostream_print(void)
     call_func1(p_strstreambuf_dtor, &ssb_test3);
 }
 
+static void test_istream(void)
+{
+    istream is1, is2, *pis;
+    filebuf fb1, fb2, *pfb;
+    const char filename1[] = "test1";
+    const char filename2[] = "test2";
+
+    memset(&is1, 0xab, sizeof(istream));
+    memset(&is2, 0xab, sizeof(istream));
+    memset(&fb1, 0xab, sizeof(filebuf));
+    memset(&fb2, 0xab, sizeof(filebuf));
+
+    /* constructors/destructors */
+    pis = call_func3(p_istream_sb_ctor, &is1, NULL, TRUE);
+    ok(pis == &is1, "wrong return, expected %p got %p\n", &is1, pis);
+    ok(is1.extract_delim == 0, "expected 0 got %d\n", is1.extract_delim);
+    ok(is1.count == 0, "expected 0 got %d\n", is1.count);
+    ok(is1.base_ios.sb == NULL, "expected %p got %p\n", NULL, is1.base_ios.sb);
+    ok(is1.base_ios.state == IOSTATE_badbit, "expected %d got %d\n", IOSTATE_badbit, is1.base_ios.state);
+    ok(is1.base_ios.flags == FLAGS_skipws, "expected %d got %d\n", FLAGS_skipws, is1.base_ios.flags);
+    call_func1(p_istream_vbase_dtor, &is1);
+    is1.extract_delim = is1.count = 0xabababab;
+    memset(&is1.base_ios, 0xab, sizeof(ios));
+    is1.base_ios.delbuf = 0;
+    pis = call_func3(p_istream_sb_ctor, &is1, NULL, FALSE);
+    ok(pis == &is1, "wrong return, expected %p got %p\n", &is1, pis);
+    ok(is1.extract_delim == 0, "expected 0 got %d\n", is1.extract_delim);
+    ok(is1.count == 0, "expected 0 got %d\n", is1.count);
+    ok(is1.base_ios.sb == NULL, "expected %p got %p\n", NULL, is1.base_ios.sb);
+    ok(is1.base_ios.state == (0xabababab|IOSTATE_badbit), "expected %d got %d\n",
+        0xabababab|IOSTATE_badbit, is1.base_ios.state);
+    ok(is1.base_ios.flags == 0xabababab, "expected %d got %d\n", 0xabababab, is1.base_ios.flags);
+    call_func1(p_istream_dtor, &is1.base_ios);
+    pis = call_func3(p_istream_sb_ctor, &is1, &fb1.base, FALSE);
+    ok(pis == &is1, "wrong return, expected %p got %p\n", &is1, pis);
+    ok(is1.extract_delim == 0, "expected 0 got %d\n", is1.extract_delim);
+    ok(is1.count == 0, "expected 0 got %d\n", is1.count);
+    ok(is1.base_ios.sb == &fb1.base, "expected %p got %p\n", &fb1.base, is1.base_ios.sb);
+    ok(is1.base_ios.state == 0xabababab, "expected %d got %d\n", 0xabababab, is1.base_ios.state);
+    ok(is1.base_ios.flags == 0xabababab, "expected %d got %d\n", 0xabababab, is1.base_ios.flags);
+    call_func1(p_istream_dtor, &is1.base_ios);
+    call_func1(p_filebuf_ctor, &fb1);
+    pfb = call_func4(p_filebuf_open, &fb1, filename1, OPENMODE_in|OPENMODE_out, filebuf_openprot);
+    ok(pfb == &fb1, "wrong return, expected %p got %p\n", &fb1, pfb);
+    ok(fb1.base.allocated == 1, "expected %d got %d\n", 1, fb1.base.allocated);
+    pis = call_func3(p_istream_sb_ctor, &is1, &fb1.base, TRUE);
+    ok(pis == &is1, "wrong return, expected %p got %p\n", &is1, pis);
+    ok(is1.extract_delim == 0, "expected 0 got %d\n", is1.extract_delim);
+    ok(is1.count == 0, "expected 0 got %d\n", is1.count);
+    ok(is1.base_ios.sb == &fb1.base, "expected %p got %p\n", &fb1.base, is1.base_ios.sb);
+    ok(is1.base_ios.state == IOSTATE_goodbit, "expected %d got %d\n", IOSTATE_goodbit, is1.base_ios.state);
+    ok(is1.base_ios.flags == FLAGS_skipws, "expected %d got %d\n", FLAGS_skipws, is1.base_ios.flags);
+    pis = call_func2(p_istream_ctor, &is2, TRUE);
+    ok(pis == &is2, "wrong return, expected %p got %p\n", &is2, pis);
+    ok(is2.extract_delim == 0, "expected 0 got %d\n", is2.extract_delim);
+    ok(is2.count == 0, "expected 0 got %d\n", is2.count);
+    ok(is2.base_ios.sb == NULL, "expected %p got %p\n", NULL, is2.base_ios.sb);
+    ok(is2.base_ios.state == IOSTATE_badbit, "expected %d got %d\n", IOSTATE_badbit, is2.base_ios.state);
+    ok(is2.base_ios.flags == FLAGS_skipws, "expected %d got %d\n", FLAGS_skipws, is2.base_ios.flags);
+    call_func1(p_istream_vbase_dtor, &is2);
+    is2.extract_delim = is2.count = 0xabababab;
+    memset(&is2.base_ios, 0xab, sizeof(ios));
+    is2.base_ios.flags &= ~FLAGS_skipws;
+    pis = call_func2(p_istream_ctor, &is2, FALSE);
+    ok(pis == &is2, "wrong return, expected %p got %p\n", &is2, pis);
+    ok(is2.extract_delim == 0, "expected 0 got %d\n", is2.extract_delim);
+    ok(is2.count == 0, "expected 0 got %d\n", is2.count);
+    ok(is2.base_ios.sb != NULL, "expected not %p got %p\n", NULL, is2.base_ios.sb);
+    ok(is2.base_ios.state == 0xabababab, "expected %d got %d\n", 0xabababab, is2.base_ios.state);
+    ok(is2.base_ios.flags == 0xabababab, "expected %d got %d\n", 0xabababab, is2.base_ios.flags);
+    call_func1(p_istream_dtor, &is2.base_ios);
+    is1.extract_delim = is1.count = 0xcdcdcdcd;
+    is1.base_ios.state = 0xcdcdcdcd;
+    is1.base_ios.flags &= ~FLAGS_skipws;
+    is2.extract_delim = is2.count = 0xabababab;
+    memset(&is2.base_ios, 0xab, sizeof(ios));
+    is2.base_ios.flags &= ~FLAGS_skipws;
+    is2.base_ios.delbuf = 0;
+    pis = call_func3(p_istream_copy_ctor, &is2, &is1, FALSE);
+    ok(pis == &is2, "wrong return, expected %p got %p\n", &is2, pis);
+    ok(is2.extract_delim == 0, "expected 0 got %d\n", is2.extract_delim);
+    ok(is2.count == 0, "expected 0 got %d\n", is2.count);
+    ok(is2.base_ios.sb == is1.base_ios.sb, "expected %p got %p\n", is1.base_ios.sb, is2.base_ios.sb);
+    ok(is2.base_ios.state == 0xabababab, "expected %d got %d\n", 0xabababab, is2.base_ios.state);
+    ok(is2.base_ios.flags == 0xabababab, "expected %d got %d\n", 0xabababab, is2.base_ios.flags);
+    call_func1(p_istream_dtor, &is2.base_ios);
+    is2.extract_delim = is2.count = 0xabababab;
+    memset(&is2.base_ios, 0xab, sizeof(ios));
+    pis = call_func3(p_istream_copy_ctor, &is2, &is1, TRUE);
+    ok(pis == &is2, "wrong return, expected %p got %p\n", &is2, pis);
+    ok(is2.extract_delim == 0, "expected 0 got %d\n", is2.extract_delim);
+    ok(is2.count == 0, "expected 0 got %d\n", is2.count);
+    ok(is2.base_ios.sb == is1.base_ios.sb, "expected %p got %p\n", is1.base_ios.sb, is2.base_ios.sb);
+    ok(is2.base_ios.state == IOSTATE_goodbit, "expected %d got %d\n", IOSTATE_goodbit, is2.base_ios.state);
+    ok(is2.base_ios.flags == FLAGS_skipws, "expected %d got %d\n", FLAGS_skipws, is2.base_ios.flags);
+
+    /* assignment */
+    is2.extract_delim = is2.count = 0xabababab;
+    is2.base_ios.sb = (streambuf*) 0xabababab;
+    is2.base_ios.state = 0xabababab;
+    is2.base_ios.special[0] = 0xabababab;
+    is2.base_ios.delbuf = 0;
+    is2.base_ios.tie = (ostream*) 0xabababab;
+    is2.base_ios.flags = 0xabababab;
+    is2.base_ios.precision = 0xabababab;
+    is2.base_ios.width = 0xabababab;
+    pis = call_func2(p_istream_assign, &is2, &is1);
+    ok(pis == &is2, "wrong return, expected %p got %p\n", &is2, pis);
+    ok(is2.extract_delim == 0xabababab, "expected %d got %d\n", 0xabababab, is2.extract_delim);
+    ok(is2.count == 0, "expected 0 got %d\n", is2.count);
+    ok(is2.base_ios.sb == is1.base_ios.sb, "expected %p got %p\n", is1.base_ios.sb, is2.base_ios.sb);
+    ok(is2.base_ios.state == IOSTATE_goodbit, "expected %d got %d\n", IOSTATE_goodbit, is2.base_ios.state);
+    ok(is2.base_ios.special[0] == 0xabababab, "expected %d got %d\n", 0xabababab, is2.base_ios.fill);
+    ok(is2.base_ios.delbuf == 0, "expected 0 got %d\n", is2.base_ios.delbuf);
+    ok(is2.base_ios.tie == NULL, "expected %p got %p\n", NULL, is2.base_ios.tie);
+    ok(is2.base_ios.flags == FLAGS_skipws, "expected %d got %d\n", FLAGS_skipws, is2.base_ios.flags);
+    ok(is2.base_ios.precision == 6, "expected 6 got %d\n", is2.base_ios.precision);
+    ok(is2.base_ios.width == 0, "expected 0 got %d\n", is2.base_ios.width);
+if (0) /* crashes on native */
+    pis = call_func2(p_istream_assign, &is2, NULL);
+    is2.extract_delim = is2.count = 0xabababab;
+    is2.base_ios.sb = (streambuf*) 0xabababab;
+    is2.base_ios.state = 0xabababab;
+    is2.base_ios.special[0] = 0xabababab;
+    is2.base_ios.delbuf = 0;
+    is2.base_ios.tie = (ostream*) 0xabababab;
+    is2.base_ios.flags = 0xabababab;
+    is2.base_ios.precision = 0xabababab;
+    is2.base_ios.width = 0xabababab;
+    pis = call_func2(p_istream_assign_sb, &is2, NULL);
+    ok(pis == &is2, "wrong return, expected %p got %p\n", &is2, pis);
+    ok(is2.extract_delim == 0xabababab, "expected %d got %d\n", 0xabababab, is2.extract_delim);
+    ok(is2.count == 0, "expected 0 got %d\n", is2.count);
+    ok(is2.base_ios.sb == NULL, "expected %p got %p\n", NULL, is2.base_ios.sb);
+    ok(is2.base_ios.state == IOSTATE_badbit, "expected %d got %d\n", IOSTATE_badbit, is2.base_ios.state);
+    ok(is2.base_ios.special[0] == 0xabababab, "expected %d got %d\n", 0xabababab, is2.base_ios.fill);
+    ok(is2.base_ios.delbuf == 0, "expected 0 got %d\n", is2.base_ios.delbuf);
+    ok(is2.base_ios.tie == NULL, "expected %p got %p\n", NULL, is2.base_ios.tie);
+    ok(is2.base_ios.flags == FLAGS_skipws, "expected %d got %d\n", FLAGS_skipws, is2.base_ios.flags);
+    ok(is2.base_ios.precision == 6, "expected 6 got %d\n", is2.base_ios.precision);
+    ok(is2.base_ios.width == 0, "expected 0 got %d\n", is2.base_ios.width);
+    call_func1(p_filebuf_ctor, &fb2);
+    pfb = call_func4(p_filebuf_open, &fb2, filename2, OPENMODE_in|OPENMODE_out, filebuf_openprot);
+    ok(pfb == &fb2, "wrong return, expected %p got %p\n", &fb2, pfb);
+    ok(fb2.base.allocated == 1, "expected %d got %d\n", 1, fb2.base.allocated);
+    pis = call_func2(p_istream_assign_sb, &is2, &fb2.base);
+    ok(pis == &is2, "wrong return, expected %p got %p\n", &is2, pis);
+    ok(is2.extract_delim == 0xabababab, "expected %d got %d\n", 0xabababab, is2.extract_delim);
+    ok(is2.count == 0, "expected 0 got %d\n", is2.count);
+    ok(is2.base_ios.sb == &fb2.base, "expected %p got %p\n", &fb2.base, is2.base_ios.sb);
+    ok(is2.base_ios.state == IOSTATE_goodbit, "expected %d got %d\n", IOSTATE_goodbit, is2.base_ios.state);
+
+    call_func1(p_istream_vbase_dtor, &is1);
+    call_func1(p_istream_vbase_dtor, &is2);
+    call_func1(p_filebuf_dtor, &fb1);
+    call_func1(p_filebuf_dtor, &fb2);
+    ok(_unlink(filename1) == 0, "Couldn't unlink file named '%s'\n", filename1);
+    ok(_unlink(filename2) == 0, "Couldn't unlink file named '%s'\n", filename2);
+}
+
 START_TEST(msvcirt)
 {
     if(!init())
@@ -3383,6 +3576,7 @@ START_TEST(msvcirt)
     test_ios();
     test_ostream();
     test_ostream_print();
+    test_istream();
 
     FreeLibrary(msvcrt);
     FreeLibrary(msvcirt);
-- 
2.7.4




More information about the wine-patches mailing list