Module: wine Branch: master Commit: 0257ebc838395dd9934e4ab682483eba72963c5e URL: http://source.winehq.org/git/wine.git/?a=commit;h=0257ebc838395dd9934e4ab682...
Author: Iván Matellanes matellanesivan@gmail.com Date: Thu Sep 17 11:06:50 2015 +0200
msvcirt: Implement strstreambuf::doallocate.
---
dlls/msvcirt/msvcirt.c | 37 +++++++++++++++++++++++++++++++++++-- dlls/msvcirt/tests/msvcirt.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 2 deletions(-)
diff --git a/dlls/msvcirt/msvcirt.c b/dlls/msvcirt/msvcirt.c index 4b826db..d2c39eb 100644 --- a/dlls/msvcirt/msvcirt.c +++ b/dlls/msvcirt/msvcirt.c @@ -1280,8 +1280,41 @@ strstreambuf* __thiscall strstreambuf_scalar_dtor(strstreambuf *this, unsigned i DEFINE_THISCALL_WRAPPER(strstreambuf_doallocate, 4) int __thiscall strstreambuf_doallocate(strstreambuf *this) { - FIXME("(%p) stub\n", this); - return EOF; + char *prev_buffer = this->base.base, *new_buffer; + LONG prev_size = this->base.ebuf - this->base.base, new_size; + + TRACE("(%p)\n", this); + + /* calculate the size of the new buffer */ + new_size = (prev_size > 0 ? prev_size : 0) + (this->increase > 0 ? this->increase : 1); + /* get a new buffer */ + if (this->f_alloc) + new_buffer = this->f_alloc(new_size); + else + new_buffer = MSVCRT_operator_new(new_size); + if (!new_buffer) + return EOF; + if (this->base.ebuf) { + /* copy the contents and adjust the pointers */ + memcpy(new_buffer, this->base.base, prev_size); + if (this->base.egptr) { + this->base.eback += new_buffer - prev_buffer; + this->base.gptr += new_buffer - prev_buffer; + this->base.egptr += new_buffer - prev_buffer; + } + if (this->base.epptr) { + this->base.pbase += new_buffer - prev_buffer; + this->base.pptr += new_buffer - prev_buffer; + this->base.epptr += new_buffer - prev_buffer; + } + /* free the old buffer */ + if (this->f_free) + this->f_free(this->base.base); + else + MSVCRT_operator_delete(this->base.base); + } + streambuf_setb(&this->base, new_buffer, new_buffer + new_size, 0); + return 1; }
/* ?freeze@strstreambuf@@QAEXH@Z */ diff --git a/dlls/msvcirt/tests/msvcirt.c b/dlls/msvcirt/tests/msvcirt.c index aaa9f1c..c7398d6 100644 --- a/dlls/msvcirt/tests/msvcirt.c +++ b/dlls/msvcirt/tests/msvcirt.c @@ -193,6 +193,7 @@ static strstreambuf* (*__thiscall p_strstreambuf_buffer_ctor)(strstreambuf*, cha static strstreambuf* (*__thiscall p_strstreambuf_ubuffer_ctor)(strstreambuf*, unsigned char*, int, unsigned char*); static strstreambuf* (*__thiscall p_strstreambuf_ctor)(strstreambuf*); static void (*__thiscall p_strstreambuf_dtor)(strstreambuf*); +static int (*__thiscall p_strstreambuf_doallocate)(strstreambuf*); static void (*__thiscall p_strstreambuf_freeze)(strstreambuf*, int);
/* ios */ @@ -346,6 +347,7 @@ static BOOL init(void) SET(p_strstreambuf_ubuffer_ctor, "??0strstreambuf@@QEAA@PEAEH0@Z"); SET(p_strstreambuf_ctor, "??0strstreambuf@@QEAA@XZ"); SET(p_strstreambuf_dtor, "??1strstreambuf@@UEAA@XZ"); + SET(p_strstreambuf_doallocate, "?doallocate@strstreambuf@@MEAAHXZ"); SET(p_strstreambuf_freeze, "?freeze@strstreambuf@@QEAAXH@Z");
SET(p_ios_copy_ctor, "??0ios@@IEAA@AEBV0@@Z"); @@ -419,6 +421,7 @@ static BOOL init(void) SET(p_strstreambuf_ubuffer_ctor, "??0strstreambuf@@QAE@PAEH0@Z"); SET(p_strstreambuf_ctor, "??0strstreambuf@@QAE@XZ"); SET(p_strstreambuf_dtor, "??1strstreambuf@@UAE@XZ"); + SET(p_strstreambuf_doallocate, "?doallocate@strstreambuf@@MAEHXZ"); SET(p_strstreambuf_freeze, "?freeze@strstreambuf@@QAEXH@Z");
SET(p_ios_copy_ctor, "??0ios@@IAE@ABV0@@Z"); @@ -1420,6 +1423,7 @@ static void test_strstreambuf(void) { strstreambuf ssb1, ssb2; char buffer[64]; + int ret;
memset(&ssb1, 0xab, sizeof(strstreambuf)); memset(&ssb2, 0xab, sizeof(strstreambuf)); @@ -1544,6 +1548,35 @@ static void test_strstreambuf(void) call_func2(p_strstreambuf_freeze, &ssb2, 0); ok(ssb2.dynamic == 1, "expected 1, got %d\n", ssb2.dynamic);
+ /* doallocate */ + ssb2.dynamic = 0; + ssb2.increase = 5; + ret = (int) call_func1(p_strstreambuf_doallocate, &ssb2); + ok(ret == 1, "return value %d\n", ret); + ok(ssb2.base.ebuf == ssb2.base.base + 5, "expected %p, got %p\n", ssb2.base.base + 5, ssb2.base.ebuf); + ssb2.base.eback = ssb2.base.base; + ssb2.base.gptr = ssb2.base.base + 2; + ssb2.base.egptr = ssb2.base.base + 4; + strcpy(ssb2.base.base, "Check"); + ret = (int) call_func1(p_strstreambuf_doallocate, &ssb2); + ok(ret == 1, "return value %d\n", ret); + ok(ssb2.base.ebuf == ssb2.base.base + 10, "expected %p, got %p\n", ssb2.base.base + 10, ssb2.base.ebuf); + ok(ssb2.base.eback == ssb2.base.base, "wrong get base, expected %p got %p\n", ssb2.base.base, ssb2.base.eback); + ok(ssb2.base.gptr == ssb2.base.base + 2, "wrong get pointer, expected %p got %p\n", ssb2.base.base + 2, ssb2.base.gptr); + ok(ssb2.base.egptr == ssb2.base.base + 4, "wrong get end, expected %p got %p\n", ssb2.base.base + 4, ssb2.base.egptr); + ok(!strncmp(ssb2.base.base, "Check", 5), "strings are not equal\n"); + ssb2.base.pbase = ssb2.base.pptr = ssb2.base.base + 4; + ssb2.base.epptr = ssb2.base.ebuf; + ssb2.increase = -3; + ret = (int) call_func1(p_strstreambuf_doallocate, &ssb2); + ok(ret == 1, "return value %d\n", ret); + ok(ssb2.base.ebuf == ssb2.base.base + 11, "expected %p, got %p\n", ssb2.base.base + 11, ssb2.base.ebuf); + ok(ssb2.base.pbase == ssb2.base.base + 4, "wrong put base, expected %p got %p\n", ssb2.base.base + 4, ssb2.base.pbase); + ok(ssb2.base.pptr == ssb2.base.base + 4, "wrong put pointer, expected %p got %p\n", ssb2.base.base + 4, ssb2.base.pptr); + ok(ssb2.base.epptr == ssb2.base.base + 10, "wrong put end, expected %p got %p\n", ssb2.base.base + 10, ssb2.base.epptr); + ok(!strncmp(ssb2.base.base, "Check", 5), "strings are not equal\n"); + ssb2.dynamic = 1; + call_func1(p_strstreambuf_dtor, &ssb1); call_func1(p_strstreambuf_dtor, &ssb2); }