Module: wine Branch: master Commit: 25a02cc4a9c6e893a62a4855ea6eb4633f204804 URL: http://source.winehq.org/git/wine.git/?a=commit;h=25a02cc4a9c6e893a62a4855ea...
Author: Iván Matellanes matellanesivan@gmail.com Date: Mon Jul 18 16:00:19 2016 +0100
msvcirt: Implement istream::putback.
Signed-off-by: Iván Matellanes matellanes.ivan@gmail.com Signed-off-by: Piotr Caban piotr@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/msvcirt/msvcirt.c | 11 ++++++++++- dlls/msvcirt/tests/msvcirt.c | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-)
diff --git a/dlls/msvcirt/msvcirt.c b/dlls/msvcirt/msvcirt.c index 88b6a62..2e3a308 100644 --- a/dlls/msvcirt/msvcirt.c +++ b/dlls/msvcirt/msvcirt.c @@ -3301,7 +3301,16 @@ int __thiscall istream_peek(istream *this) DEFINE_THISCALL_WRAPPER(istream_putback, 8) istream* __thiscall istream_putback(istream *this, char ch) { - FIXME("(%p %c) stub\n", this, ch); + ios *base = istream_get_ios(this); + + TRACE("(%p %c)\n", this, ch); + + if (ios_good(base)) { + ios_lockbuf(base); + if (streambuf_sputbackc(base->sb, ch) == EOF) + ios_clear(base, base->state | IOSTATE_failbit); + ios_unlockbuf(base); + } return this; }
diff --git a/dlls/msvcirt/tests/msvcirt.c b/dlls/msvcirt/tests/msvcirt.c index f55ad86..4c83297 100644 --- a/dlls/msvcirt/tests/msvcirt.c +++ b/dlls/msvcirt/tests/msvcirt.c @@ -319,6 +319,7 @@ static istream* (*__thiscall p_istream_get_sb)(istream*, streambuf*, char); static istream* (*__thiscall p_istream_getline)(istream*, char*, int, char); static istream* (*__thiscall p_istream_ignore)(istream*, int, int); static int (*__thiscall p_istream_peek)(istream*); +static istream* (*__thiscall p_istream_putback)(istream*, char);
/* Emulate a __thiscall */ #ifdef __i386__ @@ -526,6 +527,7 @@ static BOOL init(void) SET(p_istream_getline, "?getline@istream@@QEAAAEAV1@PEADHD@Z"); SET(p_istream_ignore, "?ignore@istream@@QEAAAEAV1@HH@Z"); SET(p_istream_peek, "?peek@istream@@QEAAHXZ"); + SET(p_istream_putback, "?putback@istream@@QEAAAEAV1@D@Z"); } else { p_operator_new = (void*)GetProcAddress(msvcrt, "??2@YAPAXI@Z"); p_operator_delete = (void*)GetProcAddress(msvcrt, "??3@YAXPAX@Z"); @@ -655,6 +657,7 @@ static BOOL init(void) SET(p_istream_getline, "?getline@istream@@QAEAAV1@PADHD@Z"); SET(p_istream_ignore, "?ignore@istream@@QAEAAV1@HH@Z"); SET(p_istream_peek, "?peek@istream@@QAEHXZ"); + SET(p_istream_putback, "?putback@istream@@QAEAAV1@D@Z"); } SET(p_ios_static_lock, "?x_lockc@ios@@0U_CRT_CRITICAL_SECTION@@A"); SET(p_ios_lockc, "?lockc@ios@@KAXXZ"); @@ -4385,6 +4388,44 @@ if (0) /* crashes on native */ ok(is1.base_ios.state == IOSTATE_goodbit, "expected %d got %d\n", IOSTATE_goodbit, is1.base_ios.state); ok(fb1.base.gptr == NULL, "wrong get pointer, expected %p got %p\n", NULL, fb1.base.gptr);
+ /* putback */ + is1.base_ios.state = IOSTATE_goodbit; + pis = call_func2(p_istream_putback, &is1, 'a'); + ok(pis == &is1, "wrong return, expected %p got %p\n", &is1, pis); + ok(is1.base_ios.state == IOSTATE_goodbit, "expected %d got %d\n", IOSTATE_goodbit, is1.base_ios.state); + ok(fb1.base.gptr == NULL, "wrong get pointer, expected %p got %p\n", NULL, fb1.base.gptr); + fd = fb1.fd; + fb1.fd = -1; + pis = call_func2(p_istream_putback, &is1, 'a'); + ok(pis == &is1, "wrong return, expected %p got %p\n", &is1, pis); + ok(is1.base_ios.state == IOSTATE_failbit, "expected %d got %d\n", IOSTATE_failbit, is1.base_ios.state); + fb1.fd = fd; + fb1.base.eback = fb1.base.base; + fb1.base.gptr = fb1.base.base + 15; + fb1.base.egptr = fb1.base.base + 30; + pis = call_func2(p_istream_putback, &is1, -40); + ok(pis == &is1, "wrong return, expected %p got %p\n", &is1, pis); + ok(is1.base_ios.state == IOSTATE_failbit, "expected %d got %d\n", IOSTATE_failbit, is1.base_ios.state); + ok(fb1.base.gptr == fb1.base.base + 15, "wrong get pointer, expected %p got %p\n", fb1.base.base + 15, fb1.base.gptr); + is1.base_ios.state = IOSTATE_badbit; + pis = call_func2(p_istream_putback, &is1, -40); + ok(pis == &is1, "wrong return, expected %p got %p\n", &is1, pis); + ok(is1.base_ios.state == IOSTATE_badbit, "expected %d got %d\n", IOSTATE_badbit, is1.base_ios.state); + ok(fb1.base.gptr == fb1.base.base + 15, "wrong get pointer, expected %p got %p\n", fb1.base.base + 15, fb1.base.gptr); + is1.base_ios.state = IOSTATE_eofbit; + pis = call_func2(p_istream_putback, &is1, -40); + ok(pis == &is1, "wrong return, expected %p got %p\n", &is1, pis); + ok(is1.base_ios.state == IOSTATE_eofbit, "expected %d got %d\n", IOSTATE_eofbit, is1.base_ios.state); + ok(fb1.base.gptr == fb1.base.base + 15, "wrong get pointer, expected %p got %p\n", fb1.base.base + 15, fb1.base.gptr); + is1.base_ios.state = IOSTATE_goodbit; +if (0) /* crashes on native */ + is1.base_ios.sb = NULL; + pis = call_func2(p_istream_putback, &is1, -40); + ok(pis == &is1, "wrong return, expected %p got %p\n", &is1, pis); + ok(is1.base_ios.state == IOSTATE_goodbit, "expected %d got %d\n", IOSTATE_goodbit, is1.base_ios.state); + ok(fb1.base.gptr == fb1.base.base + 14, "wrong get pointer, expected %p got %p\n", fb1.base.base + 14, fb1.base.gptr); + ok(*fb1.base.gptr == -40, "expected -40 got %d\n", *fb1.base.gptr); + call_func1(p_istream_vbase_dtor, &is1); call_func1(p_istream_vbase_dtor, &is2); call_func1(p_ostream_vbase_dtor, &os);