[10/10] msvcirt: Implement strstreambuf::seekoff

Iván Matellanes matellanesivan at gmail.com
Sun Sep 13 10:43:59 CDT 2015


---
 dlls/msvcirt/msvcirt.c       |  40 +++++++++++++++-
 dlls/msvcirt/tests/msvcirt.c | 106 ++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 143 insertions(+), 3 deletions(-)

diff --git a/dlls/msvcirt/msvcirt.c b/dlls/msvcirt/msvcirt.c
index f1af27f..9547b1b 100644
--- a/dlls/msvcirt/msvcirt.c
+++ b/dlls/msvcirt/msvcirt.c
@@ -1351,8 +1351,44 @@ int __thiscall strstreambuf_overflow(strstreambuf *this, int c)
 DEFINE_THISCALL_WRAPPER(strstreambuf_seekoff, 16)
 streampos __thiscall strstreambuf_seekoff(strstreambuf *this, streamoff offset, ios_seek_dir dir, int mode)
 {
-    FIXME("(%p %d %d %d) stub\n", this, offset, dir, mode);
-    return EOF;
+    char *base[3];
+
+    TRACE("(%p %d %d %d)\n", this, offset, dir, mode);
+
+    if (dir < 0 || dir > 2 || !(mode & (OPENMODE_in|OPENMODE_out)))
+        return EOF;
+    /* read buffer */
+    if (mode & OPENMODE_in) {
+        base[0] = this->base.eback;
+        base[1] = this->base.gptr;
+        base[2] = this->base.egptr;
+        if (this->base.gptr >= this->base.egptr)
+            call_streambuf_underflow(&this->base);
+        if (base[dir] + offset < this->base.eback || base[dir] + offset > this->base.egptr)
+            return EOF;
+        this->base.gptr = base[dir] + offset;
+    }
+    /* write buffer */
+    if (mode & OPENMODE_out) {
+        if (!this->base.epptr && call_streambuf_overflow(&this->base, EOF) == EOF)
+            return EOF;
+        base[0] = this->base.pbase;
+        base[1] = this->base.pptr;
+        base[2] = this->base.epptr;
+        if (base[dir] + offset < this->base.pbase)
+            return EOF;
+        if (base[dir] + offset > this->base.epptr) {
+            /* make room if the buffer is dynamic */
+            if (!this->dynamic)
+                return EOF;
+            this->increase = offset;
+            if (call_streambuf_doallocate(&this->base) == EOF)
+                return EOF;
+        }
+        this->base.pptr = base[dir] + offset;
+        return this->base.pptr - base[0];
+    }
+    return this->base.gptr - base[0];
 }
 
 /* ?setbuf at strstreambuf@@UAEPAVstreambuf@@PADH at Z */
diff --git a/dlls/msvcirt/tests/msvcirt.c b/dlls/msvcirt/tests/msvcirt.c
index bb8d9a3..0a5c77a 100644
--- a/dlls/msvcirt/tests/msvcirt.c
+++ b/dlls/msvcirt/tests/msvcirt.c
@@ -196,6 +196,7 @@ static void (*__thiscall p_strstreambuf_dtor)(strstreambuf*);
 static int (*__thiscall p_strstreambuf_doallocate)(strstreambuf*);
 static void (*__thiscall p_strstreambuf_freeze)(strstreambuf*, int);
 static int (*__thiscall p_strstreambuf_overflow)(strstreambuf*, int);
+static streampos (*__thiscall p_strstreambuf_seekoff)(strstreambuf*, streamoff, ios_seek_dir, int);
 static streambuf* (*__thiscall p_strstreambuf_setbuf)(strstreambuf*, char*, int);
 static int (*__thiscall p_strstreambuf_underflow)(strstreambuf*);
 
@@ -353,6 +354,7 @@ static BOOL init(void)
         SET(p_strstreambuf_doallocate, "?doallocate at strstreambuf@@MEAAHXZ");
         SET(p_strstreambuf_freeze, "?freeze at strstreambuf@@QEAAXH at Z");
         SET(p_strstreambuf_overflow, "?overflow at strstreambuf@@UEAAHH at Z");
+        SET(p_strstreambuf_seekoff, "?seekoff at strstreambuf@@UEAAJJW4seek_dir at ios@@H at Z");
         SET(p_strstreambuf_setbuf, "?setbuf at strstreambuf@@UEAAPEAVstreambuf@@PEADH at Z");
         SET(p_strstreambuf_underflow, "?underflow at strstreambuf@@UEAAHXZ");
 
@@ -430,6 +432,7 @@ static BOOL init(void)
         SET(p_strstreambuf_doallocate, "?doallocate at strstreambuf@@MAEHXZ");
         SET(p_strstreambuf_freeze, "?freeze at strstreambuf@@QAEXH at Z");
         SET(p_strstreambuf_overflow, "?overflow at strstreambuf@@UAEHH at Z");
+        SET(p_strstreambuf_seekoff, "?seekoff at strstreambuf@@UAEJJW4seek_dir at ios@@H at Z");
         SET(p_strstreambuf_setbuf, "?setbuf at strstreambuf@@UAEPAVstreambuf@@PADH at Z");
         SET(p_strstreambuf_underflow, "?underflow at strstreambuf@@UAEHXZ");
 
@@ -1432,7 +1435,7 @@ static void test_strstreambuf(void)
 {
     strstreambuf ssb1, ssb2;
     streambuf *pret;
-    char buffer[64];
+    char buffer[64], *pbuffer;
     int ret;
 
     memset(&ssb1, 0xab, sizeof(strstreambuf));
@@ -1690,6 +1693,107 @@ static void test_strstreambuf(void)
     ok(ssb2.base.epptr == ssb2.base.base + 28, "wrong put end, expected %p got %p\n", ssb2.base.base + 28, ssb2.base.epptr);
     ok(*(ssb2.base.pptr - 1) == 'G', "expected 'G' got %d\n", *(ssb2.base.pptr - 1));
 
+    /* seekoff */
+    ret = (int) call_func4(p_strstreambuf_seekoff, &ssb1, 0, SEEKDIR_beg, OPENMODE_in);
+    ok(ret == 0, "expected 0 got %d\n", ret);
+    ok(ssb1.base.gptr == ssb1.base.eback, "wrong get pointer, expected %p got %p\n", ssb1.base.eback, ssb1.base.gptr);
+    ret = (int) call_func4(p_strstreambuf_seekoff, &ssb1, 3, SEEKDIR_beg, OPENMODE_in);
+    ok(ret == 3, "expected 3 got %d\n", ret);
+    ok(ssb1.base.gptr == ssb1.base.eback + 3, "wrong get pointer, expected %p got %p\n", ssb1.base.eback + 3, ssb1.base.gptr);
+    ssb1.base.egptr = ssb1.base.pbase;
+    ret = (int) call_func4(p_strstreambuf_seekoff, &ssb1, 25, SEEKDIR_beg, OPENMODE_in);
+    ok(ret == EOF, "expected EOF got %d\n", ret);
+    ok(ssb1.base.gptr == ssb1.base.eback + 3, "wrong get pointer, expected %p got %p\n", ssb1.base.eback + 3, ssb1.base.gptr);
+    ssb1.base.gptr = ssb1.base.egptr;
+    ssb1.base.pptr = ssb1.base.pbase + 10;
+    ret = (int) call_func4(p_strstreambuf_seekoff, &ssb1, 25, SEEKDIR_beg, OPENMODE_in);
+    ok(ret == 25, "expected 25 got %d\n", ret);
+    ok(ssb1.base.gptr == ssb1.base.eback + 25, "wrong get pointer, expected %p got %p\n", ssb1.base.eback + 25, ssb1.base.gptr);
+    ok(ssb1.base.egptr == ssb1.base.pptr, "wrong get end, expected %p got %p\n", ssb1.base.pptr, ssb1.base.egptr);
+    ret = (int) call_func4(p_strstreambuf_seekoff, &ssb1, -24, SEEKDIR_cur, OPENMODE_in);
+    ok(ret == 1, "expected 1 got %d\n", ret);
+    ok(ssb1.base.gptr == ssb1.base.eback + 1, "wrong get pointer, expected %p got %p\n", ssb1.base.eback + 1, ssb1.base.gptr);
+    ret = (int) call_func4(p_strstreambuf_seekoff, &ssb1, -5, SEEKDIR_cur, OPENMODE_in);
+    ok(ret == EOF, "expected EOF got %d\n", ret);
+    ok(ssb1.base.gptr == ssb1.base.eback + 1, "wrong get pointer, expected %p got %p\n", ssb1.base.eback + 1, ssb1.base.gptr);
+    ret = (int) call_func4(p_strstreambuf_seekoff, &ssb1, 0, SEEKDIR_end, OPENMODE_in);
+    ok(ret == 30, "expected 30 got %d\n", ret);
+    ok(ssb1.base.gptr == ssb1.base.egptr, "wrong get pointer, expected %p got %p\n", ssb1.base.egptr, ssb1.base.gptr);
+    ssb1.base.gptr = ssb1.base.eback;
+    ret = (int) call_func4(p_strstreambuf_seekoff, &ssb1, -2, SEEKDIR_end, OPENMODE_in);
+    ok(ret == 28, "expected 28 got %d\n", ret);
+    ok(ssb1.base.gptr == ssb1.base.egptr - 2, "wrong get pointer, expected %p got %p\n", ssb1.base.egptr - 2, ssb1.base.gptr);
+    ssb1.base.gptr = ssb1.base.egptr;
+    ret = (int) call_func4(p_strstreambuf_seekoff, &ssb1, -5, SEEKDIR_end, OPENMODE_in);
+    ok(ret == 25, "expected 25 got %d\n", ret);
+    ok(ssb1.base.gptr == ssb1.base.egptr - 5, "wrong get pointer, expected %p got %p\n", ssb1.base.egptr - 5, ssb1.base.gptr);
+    ret = (int) call_func4(p_strstreambuf_seekoff, &ssb1, 1, SEEKDIR_end, OPENMODE_in);
+    ok(ret == EOF, "expected EOF got %d\n", ret);
+    ok(ssb1.base.gptr == ssb1.base.egptr - 5, "wrong get pointer, expected %p got %p\n", ssb1.base.egptr - 5, ssb1.base.gptr);
+    ret = (int) call_func4(p_strstreambuf_seekoff, &ssb1, 3, SEEKDIR_beg, OPENMODE_out);
+    ok(ret == 3, "expected 3 got %d\n", ret);
+    ok(ssb1.base.pptr == ssb1.base.pbase + 3, "wrong put pointer, expected %p got %p\n", ssb1.base.pbase + 3, ssb1.base.pptr);
+    ret = (int) call_func4(p_strstreambuf_seekoff, &ssb1, -2, SEEKDIR_beg, OPENMODE_out);
+    ok(ret == EOF, "expected EOF got %d\n", ret);
+    ok(ssb1.base.pptr == ssb1.base.pbase + 3, "wrong put pointer, expected %p got %p\n", ssb1.base.pbase + 3, ssb1.base.pptr);
+    ret = (int) call_func4(p_strstreambuf_seekoff, &ssb1, 50, SEEKDIR_beg, OPENMODE_out);
+    ok(ret == EOF, "expected EOF got %d\n", ret);
+    ok(ssb1.base.pptr == ssb1.base.pbase + 3, "wrong put pointer, expected %p got %p\n", ssb1.base.pbase + 3, ssb1.base.pptr);
+    ret = (int) call_func4(p_strstreambuf_seekoff, &ssb1, 5, SEEKDIR_cur, OPENMODE_out);
+    ok(ret == 8, "expected 8 got %d\n", ret);
+    ok(ssb1.base.pptr == ssb1.base.pbase + 8, "wrong put pointer, expected %p got %p\n", ssb1.base.pbase + 8, ssb1.base.pptr);
+    ret = (int) call_func4(p_strstreambuf_seekoff, &ssb1, -2, SEEKDIR_end, OPENMODE_out);
+    ok(ret == 42, "expected 42 got %d\n", ret);
+    ok(ssb1.base.pptr == ssb1.base.epptr - 2, "wrong put pointer, expected %p got %p\n", ssb1.base.epptr - 2, ssb1.base.pptr);
+    ret = (int) call_func4(p_strstreambuf_seekoff, &ssb1, 0, SEEKDIR_end, OPENMODE_out);
+    ok(ret == 44, "expected 44 got %d\n", ret);
+    ok(ssb1.base.pptr == ssb1.base.epptr, "wrong put pointer, expected %p got %p\n", ssb1.base.epptr, ssb1.base.pptr);
+    ret = (int) call_func4(p_strstreambuf_seekoff, &ssb1, 5, SEEKDIR_beg, OPENMODE_in|OPENMODE_out);
+    ok(ret == 5, "expected 5 got %d\n", ret);
+    ok(ssb1.base.gptr == ssb1.base.eback + 5, "wrong get pointer, expected %p got %p\n", ssb1.base.eback + 5, ssb1.base.gptr);
+    ok(ssb1.base.pptr == ssb1.base.pbase + 5, "wrong put pointer, expected %p got %p\n", ssb1.base.pbase + 5, ssb1.base.pptr);
+    ssb1.base.egptr = ssb1.base.pbase;
+    ret = (int) call_func4(p_strstreambuf_seekoff, &ssb1, 21, SEEKDIR_beg, OPENMODE_in|OPENMODE_out);
+    ok(ret == EOF, "expected EOF got %d\n", ret);
+    ok(ssb1.base.gptr == ssb1.base.eback + 5, "wrong get pointer, expected %p got %p\n", ssb1.base.eback + 5, ssb1.base.gptr);
+    ok(ssb1.base.pptr == ssb1.base.pbase + 5, "wrong put pointer, expected %p got %p\n", ssb1.base.pbase + 5, ssb1.base.pptr);
+    ssb1.base.egptr = ssb1.base.epptr;
+    ret = (int) call_func4(p_strstreambuf_seekoff, &ssb1, 50, SEEKDIR_beg, OPENMODE_in|OPENMODE_out);
+    ok(ret == EOF, "expected EOF got %d\n", ret);
+    ok(ssb1.base.gptr == ssb1.base.eback + 50, "wrong get pointer, expected %p got %p\n", ssb1.base.eback + 50, ssb1.base.gptr);
+    ok(ssb1.base.pptr == ssb1.base.pbase + 5, "wrong put pointer, expected %p got %p\n", ssb1.base.pbase + 5, ssb1.base.pptr);
+    ret = (int) call_func4(p_strstreambuf_seekoff, &ssb1, 2, SEEKDIR_cur, OPENMODE_in|OPENMODE_out);
+    ok(ret == 7, "expected 7 got %d\n", ret);
+    ok(ssb1.base.gptr == ssb1.base.eback + 52, "wrong get pointer, expected %p got %p\n", ssb1.base.eback + 52, ssb1.base.gptr);
+    ok(ssb1.base.pptr == ssb1.base.pbase + 7, "wrong put pointer, expected %p got %p\n", ssb1.base.pbase + 7, ssb1.base.pptr);
+    ret = (int) call_func4(p_strstreambuf_seekoff, &ssb2, 0, SEEKDIR_beg, OPENMODE_in|OPENMODE_out);
+    ok(ret == 0, "expected 0 got %d\n", ret);
+    ok(ssb2.base.gptr == ssb2.base.eback, "wrong get pointer, expected %p got %p\n", ssb2.base.eback, ssb2.base.gptr);
+    ok(ssb2.base.pptr == ssb2.base.pbase, "wrong put pointer, expected %p got %p\n", ssb2.base.pbase, ssb2.base.pptr);
+    ssb2.base.gptr = ssb2.base.egptr;
+    ssb2.base.pptr += 10;
+    ret = (int) call_func4(p_strstreambuf_seekoff, &ssb2, 5, SEEKDIR_cur, OPENMODE_in|OPENMODE_out);
+    ok(ret == 15, "expected 15 got %d\n", ret);
+    ok(ssb2.base.gptr == ssb2.base.eback + 7, "wrong get pointer, expected %p got %p\n", ssb2.base.eback + 7, ssb2.base.gptr);
+    ok(ssb2.base.egptr == ssb2.base.eback + 12, "wrong get end, expected %p got %p\n", ssb2.base.eback + 12, ssb2.base.egptr);
+    ok(ssb2.base.pptr == ssb2.base.pbase + 15, "wrong put pointer, expected %p got %p\n", ssb2.base.pbase + 15, ssb2.base.pptr);
+    ssb2.base.pptr = ssb2.base.epptr;
+    ret = (int) call_func4(p_strstreambuf_seekoff, &ssb2, -1, SEEKDIR_cur, OPENMODE_in|OPENMODE_out);
+    ok(ret == 25, "expected 25 got %d\n", ret);
+    ok(ssb2.base.gptr == ssb2.base.eback + 6, "wrong get pointer, expected %p got %p\n", ssb2.base.eback + 6, ssb2.base.gptr);
+    ok(ssb2.base.pptr == ssb2.base.pbase + 25, "wrong put pointer, expected %p got %p\n", ssb2.base.pbase + 25, ssb2.base.pptr);
+    pbuffer = ssb2.base.pbase;
+    ret = (int) call_func4(p_strstreambuf_seekoff, &ssb2, 50, SEEKDIR_beg, OPENMODE_out);
+    ok(ret == 50, "expected 50 got %d\n", ret);
+    ok(ssb2.base.gptr == ssb2.base.eback + 6, "wrong get pointer, expected %p got %p\n", ssb2.base.eback + 6, ssb2.base.gptr);
+    ok(ssb2.base.pptr == pbuffer + 50, "wrong put pointer, expected %p got %p\n", pbuffer + 50, ssb2.base.pptr);
+    ok(ssb2.increase == 50, "expected 50 got %d\n", ssb2.increase);
+    ssb2.base.epptr = NULL;
+    ssb2.increase = 8;
+    ret = (int) call_func4(p_strstreambuf_seekoff, &ssb2, 0, SEEKDIR_end, OPENMODE_out);
+    ok(ret == 74, "expected 74 got %d\n", ret);
+    ok(ssb2.base.pptr == ssb2.base.epptr, "wrong put pointer, expected %p got %p\n", ssb2.base.epptr, ssb2.base.pptr);
+
     call_func1(p_strstreambuf_dtor, &ssb1);
     call_func1(p_strstreambuf_dtor, &ssb2);
 }
-- 
2.1.4




More information about the wine-patches mailing list