[2/3] msvcirt: Add implementation of streambuf::xsputn

Iván Matellanes matellanesivan at gmail.com
Sat Jun 20 09:40:15 CDT 2015


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

diff --git a/dlls/msvcirt/msvcirt.c b/dlls/msvcirt/msvcirt.c
index 6b440fd..e8faa54 100644
--- a/dlls/msvcirt/msvcirt.c
+++ b/dlls/msvcirt/msvcirt.c
@@ -535,8 +535,25 @@ int __thiscall streambuf_xsgetn(streambuf *this, char *buffer, int count)
 DEFINE_THISCALL_WRAPPER(streambuf_xsputn, 12)
 int __thiscall streambuf_xsputn(streambuf *this, const char *data, int length)
 {
-    FIXME("(%p %p %d): stub\n", this, data, length);
-    return 0;
+    int copied = 0, chunk;
+
+    TRACE("(%p %p %d)\n", this, data, length);
+
+    while (copied < length) {
+        if (this->unbuffered || this->pptr == this->epptr) {
+            if (call_streambuf_overflow(this, data[copied]) == EOF)
+                break;
+            copied++;
+        } else {
+            chunk = this->epptr - this->pptr;
+            if (chunk > length - copied)
+                chunk = length - copied;
+            memcpy(this->pptr, data+copied, chunk);
+            this->pptr += chunk;
+            copied += chunk;
+        }
+    }
+    return copied;
 }
 
 /* ?sgetc at streambuf@@QAEHXZ */
diff --git a/dlls/msvcirt/tests/msvcirt.c b/dlls/msvcirt/tests/msvcirt.c
index c4777a2..a175531 100644
--- a/dlls/msvcirt/tests/msvcirt.c
+++ b/dlls/msvcirt/tests/msvcirt.c
@@ -66,6 +66,7 @@ static int (*__thiscall p_streambuf_sputc)(streambuf*, int);
 static int (*__thiscall p_streambuf_sync)(streambuf*);
 static void (*__thiscall p_streambuf_unlock)(streambuf*);
 static int (*__thiscall p_streambuf_xsgetn)(streambuf*, char*, int);
+static int (*__thiscall p_streambuf_xsputn)(streambuf*, const char*, int);
 
 /* Emulate a __thiscall */
 #ifdef __i386__
@@ -153,6 +154,7 @@ static BOOL init(void)
         SET(p_streambuf_sync, "?sync at streambuf@@UEAAHXZ");
         SET(p_streambuf_unlock, "?unlock at streambuf@@QEAAXXZ");
         SET(p_streambuf_xsgetn, "?xsgetn at streambuf@@UEAAHPEADH at Z");
+        SET(p_streambuf_xsputn, "?xsputn at streambuf@@UEAAHPEBDH at Z");
     } else {
         SET(p_streambuf_reserve_ctor, "??0streambuf@@IAE at PADH@Z");
         SET(p_streambuf_ctor, "??0streambuf@@IAE at XZ");
@@ -171,6 +173,7 @@ static BOOL init(void)
         SET(p_streambuf_sync, "?sync at streambuf@@UAEHXZ");
         SET(p_streambuf_unlock, "?unlock at streambuf@@QAEXXZ");
         SET(p_streambuf_xsgetn, "?xsgetn at streambuf@@UAEHPADH at Z");
+        SET(p_streambuf_xsputn, "?xsputn at streambuf@@UAEHPBDH at Z");
     }
 
     init_thiscall_thunk();
@@ -189,6 +192,8 @@ static int __thiscall test_streambuf_overflow(streambuf *this, int ch)
 #endif
 {
     overflow_count++;
+    if (ch == 'L') /* simulate a failure */
+        return EOF;
     if (!test_this->unbuffered)
         test_this->pptr = test_this->pbase + 5;
     return ch;
@@ -527,6 +532,38 @@ static void test_streambuf(void)
     ok(sb3.stored_char == 'G', "wrong stored character, expected 'G' got %c\n", sb3.stored_char);
     ok(underflow_count == 37, "expected 6 calls to underflow, got %d\n", underflow_count - 31);
 
+    /* xsputn */
+    ret = (int) call_func3(p_streambuf_xsputn, &sb, "Test\0ing", 8);
+    ok(ret == 8, "wrong return value, expected 8 got %d\n", ret);
+    ok(sb.pptr == sb.pbase + 9, "wrong put pointer, expected %p got %p\n", sb.pbase + 9, sb.pptr);
+    test_this = &sb2;
+    sb2.pptr = sb2.epptr - 7;
+    ret = (int) call_func3(p_streambuf_xsputn, &sb2, "Testing", 7);
+    ok(ret == 7, "wrong return value, expected 7 got %d\n", ret);
+    ok(sb2.pptr == sb2.epptr, "wrong put pointer, expected %p got %p\n", sb2.epptr, sb2.pptr);
+    ok(overflow_count == 2, "no call to overflow expected\n");
+    sb2.pptr = sb2.epptr - 5;
+    sb2.pbase[5] = 'a';
+    ret = (int) call_func3(p_streambuf_xsputn, &sb2, "Testing", 7);
+    ok(ret == 7, "wrong return value, expected 7 got %d\n", ret);
+    ok(sb2.pbase[5] == 'g', "expected 'g' got %c\n", sb2.pbase[5]);
+    ok(sb2.pptr == sb2.pbase + 6, "wrong put pointer, expected %p got %p\n", sb2.pbase + 6, sb2.pptr);
+    ok(overflow_count == 3, "expected call to overflow\n");
+    sb2.pptr = sb2.epptr - 4;
+    ret = (int) call_func3(p_streambuf_xsputn, &sb2, "TestLing", 8);
+    ok(ret == 4, "wrong return value, expected 4 got %d\n", ret);
+    ok(sb2.pptr == sb2.epptr, "wrong put pointer, expected %p got %p\n", sb2.epptr, sb2.pptr);
+    ok(overflow_count == 4, "expected call to overflow\n");
+    test_this = &sb3;
+    ret = (int) call_func3(p_streambuf_xsputn, &sb3, "Testing", 7);
+    ok(ret == 7, "wrong return value, expected 7 got %d\n", ret);
+    ok(sb3.stored_char == 'G', "wrong stored character, expected 'G' got %c\n", sb3.stored_char);
+    ok(overflow_count == 11, "expected 7 calls to overflow, got %d\n", overflow_count - 4);
+    ret = (int) call_func3(p_streambuf_xsputn, &sb3, "TeLephone", 9);
+    ok(ret == 2, "wrong return value, expected 2 got %d\n", ret);
+    ok(sb3.stored_char == 'G', "wrong stored character, expected 'G' got %c\n", sb3.stored_char);
+    ok(overflow_count == 14, "expected 3 calls to overflow, got %d\n", overflow_count - 11);
+
     SetEvent(lock_arg.test[3]);
     WaitForSingleObject(thread, INFINITE);
 
-- 
2.1.4




More information about the wine-patches mailing list