[02/10] msvcirt: Implement strstreambuf constructors and destructor
Iván Matellanes
matellanesivan at gmail.com
Sun Sep 13 10:43:51 CDT 2015
---
dlls/msvcirt/msvcirt.c | 58 +++++++++++++---
dlls/msvcirt/tests/msvcirt.c | 154 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 203 insertions(+), 9 deletions(-)
diff --git a/dlls/msvcirt/msvcirt.c b/dlls/msvcirt/msvcirt.c
index 460d69a..c5bd7b5 100644
--- a/dlls/msvcirt/msvcirt.c
+++ b/dlls/msvcirt/msvcirt.c
@@ -1139,7 +1139,9 @@ int __thiscall filebuf_underflow(filebuf *this)
DEFINE_THISCALL_WRAPPER(strstreambuf_copy_ctor, 8)
strstreambuf* __thiscall strstreambuf_copy_ctor(strstreambuf *this, const strstreambuf *copy)
{
- FIXME("(%p %p) stub\n", this, copy);
+ TRACE("(%p %p)\n", this, copy);
+ *this = *copy;
+ this->base.vtable = &MSVCP_strstreambuf_vtable;
return this;
}
@@ -1148,7 +1150,14 @@ strstreambuf* __thiscall strstreambuf_copy_ctor(strstreambuf *this, const strstr
DEFINE_THISCALL_WRAPPER(strstreambuf_dynamic_ctor, 8)
strstreambuf* __thiscall strstreambuf_dynamic_ctor(strstreambuf* this, int length)
{
- FIXME("(%p %d) stub\n", this, length);
+ TRACE("(%p %d)\n", this, length);
+ streambuf_ctor(&this->base);
+ this->base.vtable = &MSVCP_strstreambuf_vtable;
+ this->dynamic = 1;
+ this->increase = length;
+ this->constant = 0;
+ this->f_alloc = NULL;
+ this->f_free = NULL;
return this;
}
@@ -1157,7 +1166,10 @@ strstreambuf* __thiscall strstreambuf_dynamic_ctor(strstreambuf* this, int lengt
DEFINE_THISCALL_WRAPPER(strstreambuf_funcs_ctor, 12)
strstreambuf* __thiscall strstreambuf_funcs_ctor(strstreambuf* this, allocFunction falloc, freeFunction ffree)
{
- FIXME("(%p %p %p) stub\n", this, falloc, ffree);
+ TRACE("(%p %p %p)\n", this, falloc, ffree);
+ strstreambuf_dynamic_ctor(this, 1);
+ this->f_alloc = falloc;
+ this->f_free = ffree;
return this;
}
@@ -1166,7 +1178,28 @@ strstreambuf* __thiscall strstreambuf_funcs_ctor(strstreambuf* this, allocFuncti
DEFINE_THISCALL_WRAPPER(strstreambuf_buffer_ctor, 16)
strstreambuf* __thiscall strstreambuf_buffer_ctor(strstreambuf *this, char *buffer, int length, char *put)
{
- FIXME("(%p %p %d %p) stub\n", this, buffer, length, put);
+ char *end_buffer;
+
+ TRACE("(%p %p %d %p)\n", this, buffer, length, put);
+
+ if (length > 0)
+ end_buffer = buffer + length;
+ else if (length == 0)
+ end_buffer = buffer + strlen(buffer);
+ else
+ end_buffer = buffer + 0x7fffffff;
+
+ streambuf_ctor(&this->base);
+ streambuf_setb(&this->base, buffer, end_buffer, 0);
+ if (put == NULL) {
+ streambuf_setg(&this->base, buffer, buffer, end_buffer);
+ } else {
+ streambuf_setg(&this->base, buffer, buffer, put);
+ streambuf_setp(&this->base, put, end_buffer);
+ }
+ this->base.vtable = &MSVCP_strstreambuf_vtable;
+ this->dynamic = 0;
+ this->constant = 1;
return this;
}
@@ -1175,8 +1208,8 @@ strstreambuf* __thiscall strstreambuf_buffer_ctor(strstreambuf *this, char *buff
DEFINE_THISCALL_WRAPPER(strstreambuf_ubuffer_ctor, 16)
strstreambuf* __thiscall strstreambuf_ubuffer_ctor(strstreambuf *this, unsigned char *buffer, int length, unsigned char *put)
{
- FIXME("(%p %p %d %p) stub\n", this, buffer, length, put);
- return this;
+ TRACE("(%p %p %d %p)\n", this, buffer, length, put);
+ return strstreambuf_buffer_ctor(this, (char*)buffer, length, (char*)put);
}
/* ??0strstreambuf@@QAE at XZ */
@@ -1184,8 +1217,8 @@ strstreambuf* __thiscall strstreambuf_ubuffer_ctor(strstreambuf *this, unsigned
DEFINE_THISCALL_WRAPPER(strstreambuf_ctor, 4)
strstreambuf* __thiscall strstreambuf_ctor(strstreambuf *this)
{
- FIXME("(%p) stub\n", this);
- return this;
+ TRACE("(%p)\n", this);
+ return strstreambuf_dynamic_ctor(this, 1);
}
/* ??1strstreambuf@@UAE at XZ */
@@ -1193,7 +1226,14 @@ strstreambuf* __thiscall strstreambuf_ctor(strstreambuf *this)
DEFINE_THISCALL_WRAPPER(strstreambuf_dtor, 4)
void __thiscall strstreambuf_dtor(strstreambuf *this)
{
- FIXME("(%p) stub\n", this);
+ TRACE("(%p)\n", this);
+ if (this->dynamic && this->base.base) {
+ if (this->f_free)
+ this->f_free(this->base.base);
+ else
+ MSVCRT_operator_delete(this->base.base);
+ }
+ streambuf_dtor(&this->base);
}
/* ??4strstreambuf@@QAEAAV0 at ABV0@@Z */
diff --git a/dlls/msvcirt/tests/msvcirt.c b/dlls/msvcirt/tests/msvcirt.c
index b381b30..1aa780f 100644
--- a/dlls/msvcirt/tests/msvcirt.c
+++ b/dlls/msvcirt/tests/msvcirt.c
@@ -27,6 +27,8 @@ typedef void (*vtable_ptr)(void);
typedef LONG streamoff;
typedef LONG streampos;
typedef int filedesc;
+typedef void* (__cdecl *allocFunction)(LONG);
+typedef void (__cdecl *freeFunction)(void*);
typedef enum {
IOSTATE_goodbit = 0x0,
@@ -102,6 +104,17 @@ typedef struct {
int close;
} filebuf;
+/* class strstreambuf */
+typedef struct {
+ streambuf base;
+ int dynamic;
+ int increase;
+ int unknown;
+ int constant;
+ allocFunction f_alloc;
+ freeFunction f_free;
+} strstreambuf;
+
/* class ios */
struct _ostream;
typedef struct {
@@ -132,6 +145,7 @@ typedef struct _ostream {
#endif
static void* (__cdecl *p_operator_new)(unsigned int);
+static void (__cdecl *p_operator_delete)(void*);
/* streambuf */
static streambuf* (*__thiscall p_streambuf_reserve_ctor)(streambuf*, char*, int);
@@ -172,6 +186,14 @@ static int (*__thiscall p_filebuf_overflow)(filebuf*, int);
static int (*__thiscall p_filebuf_underflow)(filebuf*);
static streampos (*__thiscall p_filebuf_seekoff)(filebuf*, streamoff, ios_seek_dir, int);
+/* strstreambuf */
+static strstreambuf* (*__thiscall p_strstreambuf_dynamic_ctor)(strstreambuf*, int);
+static strstreambuf* (*__thiscall p_strstreambuf_funcs_ctor)(strstreambuf*, allocFunction, freeFunction);
+static strstreambuf* (*__thiscall p_strstreambuf_buffer_ctor)(strstreambuf*, char*, int, char*);
+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*);
+
/* ios */
static ios* (*__thiscall p_ios_copy_ctor)(ios*, const ios*);
static ios* (*__thiscall p_ios_ctor)(ios*);
@@ -278,6 +300,7 @@ static BOOL init(void)
if(sizeof(void*) == 8) { /* 64-bit initialization */
p_operator_new = (void*)GetProcAddress(msvcrt, "??2 at YAPEAX_K@Z");
+ p_operator_delete = (void*)GetProcAddress(msvcrt, "??3 at YAXPEAX@Z");
SET(p_streambuf_reserve_ctor, "??0streambuf@@IEAA at PEADH@Z");
SET(p_streambuf_ctor, "??0streambuf@@IEAA at XZ");
@@ -316,6 +339,13 @@ static BOOL init(void)
SET(p_filebuf_underflow, "?underflow at filebuf@@UEAAHXZ");
SET(p_filebuf_seekoff, "?seekoff at filebuf@@UEAAJJW4seek_dir at ios@@H at Z");
+ SET(p_strstreambuf_dynamic_ctor, "??0strstreambuf@@QEAA at H@Z");
+ SET(p_strstreambuf_funcs_ctor, "??0strstreambuf@@QEAA at P6APEAXJ@ZP6AXPEAX at Z@Z");
+ SET(p_strstreambuf_buffer_ctor, "??0strstreambuf@@QEAA at PEADH0@Z");
+ SET(p_strstreambuf_ubuffer_ctor, "??0strstreambuf@@QEAA at PEAEH0@Z");
+ SET(p_strstreambuf_ctor, "??0strstreambuf@@QEAA at XZ");
+ SET(p_strstreambuf_dtor, "??1strstreambuf@@UEAA at XZ");
+
SET(p_ios_copy_ctor, "??0ios@@IEAA at AEBV0@@Z");
SET(p_ios_ctor, "??0ios@@IEAA at XZ");
SET(p_ios_sb_ctor, "??0ios@@QEAA at PEAVstreambuf@@@Z");
@@ -342,6 +372,7 @@ static BOOL init(void)
SET(p_ios_pword, "?pword at ios@@QEBAAEAPEAXH at Z");
} else {
p_operator_new = (void*)GetProcAddress(msvcrt, "??2 at YAPAXI@Z");
+ p_operator_delete = (void*)GetProcAddress(msvcrt, "??3 at YAXPAX@Z");
SET(p_streambuf_reserve_ctor, "??0streambuf@@IAE at PADH@Z");
SET(p_streambuf_ctor, "??0streambuf@@IAE at XZ");
@@ -380,6 +411,13 @@ static BOOL init(void)
SET(p_filebuf_underflow, "?underflow at filebuf@@UAEHXZ");
SET(p_filebuf_seekoff, "?seekoff at filebuf@@UAEJJW4seek_dir at ios@@H at Z");
+ SET(p_strstreambuf_dynamic_ctor, "??0strstreambuf@@QAE at H@Z");
+ SET(p_strstreambuf_funcs_ctor, "??0strstreambuf@@QAE at P6APAXJ@ZP6AXPAX at Z@Z");
+ SET(p_strstreambuf_buffer_ctor, "??0strstreambuf@@QAE at PADH0@Z");
+ SET(p_strstreambuf_ubuffer_ctor, "??0strstreambuf@@QAE at PAEH0@Z");
+ SET(p_strstreambuf_ctor, "??0strstreambuf@@QAE at XZ");
+ SET(p_strstreambuf_dtor, "??1strstreambuf@@UAE at XZ");
+
SET(p_ios_copy_ctor, "??0ios@@IAE at ABV0@@Z");
SET(p_ios_ctor, "??0ios@@IAE at XZ");
SET(p_ios_sb_ctor, "??0ios@@QAE at PAVstreambuf@@@Z");
@@ -1375,6 +1413,121 @@ static void test_filebuf(void)
CloseHandle(thread);
}
+static void test_strstreambuf(void)
+{
+ strstreambuf ssb1, ssb2;
+ char buffer[64];
+
+ memset(&ssb1, 0xab, sizeof(strstreambuf));
+ memset(&ssb2, 0xab, sizeof(strstreambuf));
+
+ /* constructors/destructor */
+ call_func2(p_strstreambuf_dynamic_ctor, &ssb1, 64);
+ ok(ssb1.base.allocated == 0, "wrong allocate value, expected 0 got %d\n", ssb1.base.allocated);
+ ok(ssb1.base.unbuffered == 0, "wrong unbuffered value, expected 0 got %d\n", ssb1.base.unbuffered);
+ ok(ssb1.dynamic == 1, "expected 1, got %d\n", ssb1.dynamic);
+ ok(ssb1.increase == 64, "expected 64, got %d\n", ssb1.increase);
+ ok(ssb1.constant == 0, "expected 0, got %d\n", ssb1.constant);
+ ok(ssb1.f_alloc == NULL, "expected %p, got %p\n", NULL, ssb1.f_alloc);
+ ok(ssb1.f_free == NULL, "expected %p, got %p\n", NULL, ssb1.f_free);
+ call_func1(p_strstreambuf_dtor, &ssb1);
+ call_func3(p_strstreambuf_funcs_ctor, &ssb2, (allocFunction)p_operator_new, p_operator_delete);
+ ok(ssb2.base.allocated == 0, "wrong allocate value, expected 0 got %d\n", ssb2.base.allocated);
+ ok(ssb2.base.unbuffered == 0, "wrong unbuffered value, expected 0 got %d\n", ssb2.base.unbuffered);
+ ok(ssb2.dynamic == 1, "expected 1, got %d\n", ssb2.dynamic);
+ ok(ssb2.increase == 1, "expected 1, got %d\n", ssb2.increase);
+ ok(ssb2.constant == 0, "expected 0, got %d\n", ssb2.constant);
+ ok(ssb2.f_alloc == (allocFunction)p_operator_new, "expected %p, got %p\n", p_operator_new, ssb2.f_alloc);
+ ok(ssb2.f_free == p_operator_delete, "expected %p, got %p\n", p_operator_delete, ssb2.f_free);
+ call_func1(p_strstreambuf_dtor, &ssb2);
+ memset(&ssb1, 0xab, sizeof(strstreambuf));
+ memset(&ssb2, 0xab, sizeof(strstreambuf));
+ call_func4(p_strstreambuf_buffer_ctor, &ssb1, buffer, 64, buffer + 20);
+ ok(ssb1.base.allocated == 0, "wrong allocate value, expected 0 got %d\n", ssb1.base.allocated);
+ ok(ssb1.base.unbuffered == 0, "wrong unbuffered value, expected 0 got %d\n", ssb1.base.unbuffered);
+ ok(ssb1.base.base == buffer, "wrong buffer, expected %p got %p\n", buffer, ssb1.base.base);
+ ok(ssb1.base.ebuf == buffer + 64, "wrong buffer end, expected %p got %p\n", buffer + 64, ssb1.base.ebuf);
+ ok(ssb1.base.eback == buffer, "wrong get base, expected %p got %p\n", buffer, ssb1.base.eback);
+ ok(ssb1.base.gptr == buffer, "wrong get pointer, expected %p got %p\n", buffer, ssb1.base.gptr);
+ ok(ssb1.base.egptr == buffer + 20, "wrong get end, expected %p got %p\n", buffer + 20, ssb1.base.egptr);
+ ok(ssb1.base.pbase == buffer + 20, "wrong put base, expected %p got %p\n", buffer + 20, ssb1.base.pbase);
+ ok(ssb1.base.pptr == buffer + 20, "wrong put pointer, expected %p got %p\n", buffer + 20, ssb1.base.pptr);
+ ok(ssb1.base.epptr == buffer + 64, "wrong put end, expected %p got %p\n", buffer + 64, ssb1.base.epptr);
+ ok(ssb1.dynamic == 0, "expected 0, got %d\n", ssb1.dynamic);
+ ok(ssb1.constant == 1, "expected 1, got %d\n", ssb1.constant);
+ call_func1(p_strstreambuf_dtor, &ssb1);
+ strcpy(buffer, "Test");
+ call_func4(p_strstreambuf_buffer_ctor, &ssb2, buffer, 0, buffer + 20);
+ ok(ssb2.base.allocated == 0, "wrong allocate value, expected 0 got %d\n", ssb2.base.allocated);
+ ok(ssb2.base.unbuffered == 0, "wrong unbuffered value, expected 0 got %d\n", ssb2.base.unbuffered);
+ ok(ssb2.base.base == buffer, "wrong buffer, expected %p got %p\n", buffer, ssb2.base.base);
+ ok(ssb2.base.ebuf == buffer + 4, "wrong buffer end, expected %p got %p\n", buffer + 4, ssb2.base.ebuf);
+ ok(ssb2.base.eback == buffer, "wrong get base, expected %p got %p\n", buffer, ssb2.base.eback);
+ ok(ssb2.base.gptr == buffer, "wrong get pointer, expected %p got %p\n", buffer, ssb2.base.gptr);
+ ok(ssb2.base.egptr == buffer + 20, "wrong get end, expected %p got %p\n", buffer + 20, ssb2.base.egptr);
+ ok(ssb2.base.pbase == buffer + 20, "wrong put base, expected %p got %p\n", buffer + 20, ssb2.base.pbase);
+ ok(ssb2.base.pptr == buffer + 20, "wrong put pointer, expected %p got %p\n", buffer + 20, ssb2.base.pptr);
+ ok(ssb2.base.epptr == buffer + 4, "wrong put end, expected %p got %p\n", buffer + 4, ssb2.base.epptr);
+ ok(ssb2.dynamic == 0, "expected 0, got %d\n", ssb2.dynamic);
+ ok(ssb2.constant == 1, "expected 1, got %d\n", ssb2.constant);
+ call_func1(p_strstreambuf_dtor, &ssb2);
+ memset(&ssb1, 0xab, sizeof(strstreambuf));
+ memset(&ssb2, 0xab, sizeof(strstreambuf));
+ call_func4(p_strstreambuf_buffer_ctor, &ssb1, NULL, 16, buffer + 20);
+ ok(ssb1.base.allocated == 0, "wrong allocate value, expected 0 got %d\n", ssb1.base.allocated);
+ ok(ssb1.base.unbuffered == 0, "wrong unbuffered value, expected 0 got %d\n", ssb1.base.unbuffered);
+ ok(ssb1.base.base == NULL, "wrong buffer, expected %p got %p\n", NULL, ssb1.base.base);
+ ok(ssb1.base.ebuf == (char*)16, "wrong buffer end, expected %p got %p\n", (char*)16, ssb1.base.ebuf);
+ ok(ssb1.base.eback == NULL, "wrong get base, expected %p got %p\n", NULL, ssb1.base.eback);
+ ok(ssb1.base.gptr == NULL, "wrong get pointer, expected %p got %p\n", NULL, ssb1.base.gptr);
+ ok(ssb1.base.egptr == buffer + 20, "wrong get end, expected %p got %p\n", buffer + 20, ssb1.base.egptr);
+ ok(ssb1.base.pbase == buffer + 20, "wrong put base, expected %p got %p\n", buffer + 20, ssb1.base.pbase);
+ ok(ssb1.base.pptr == buffer + 20, "wrong put pointer, expected %p got %p\n", buffer + 20, ssb1.base.pptr);
+ ok(ssb1.base.epptr == (char*)16, "wrong put end, expected %p got %p\n", (char*)16, ssb1.base.epptr);
+ ok(ssb1.dynamic == 0, "expected 0, got %d\n", ssb1.dynamic);
+ ok(ssb1.constant == 1, "expected 1, got %d\n", ssb1.constant);
+ call_func1(p_strstreambuf_dtor, &ssb1);
+ call_func4(p_strstreambuf_buffer_ctor, &ssb2, buffer, 0, NULL);
+ ok(ssb2.base.allocated == 0, "wrong allocate value, expected 0 got %d\n", ssb2.base.allocated);
+ ok(ssb2.base.unbuffered == 0, "wrong unbuffered value, expected 0 got %d\n", ssb2.base.unbuffered);
+ ok(ssb2.base.base == buffer, "wrong buffer, expected %p got %p\n", buffer, ssb2.base.base);
+ ok(ssb2.base.ebuf == buffer + 4, "wrong buffer end, expected %p got %p\n", buffer + 4, ssb2.base.ebuf);
+ ok(ssb2.base.eback == buffer, "wrong get base, expected %p got %p\n", buffer, ssb2.base.eback);
+ ok(ssb2.base.gptr == buffer, "wrong get pointer, expected %p got %p\n", buffer, ssb2.base.gptr);
+ ok(ssb2.base.egptr == buffer + 4, "wrong get end, expected %p got %p\n", buffer + 4, ssb2.base.egptr);
+ ok(ssb2.base.pbase == NULL, "wrong put base, expected %p got %p\n", NULL, ssb2.base.pbase);
+ ok(ssb2.base.pptr == NULL, "wrong put pointer, expected %p got %p\n", NULL, ssb2.base.pptr);
+ ok(ssb2.base.epptr == NULL, "wrong put end, expected %p got %p\n", NULL, ssb2.base.epptr);
+ ok(ssb2.dynamic == 0, "expected 0, got %d\n", ssb2.dynamic);
+ ok(ssb2.constant == 1, "expected 1, got %d\n", ssb2.constant);
+ call_func1(p_strstreambuf_dtor, &ssb2);
+ memset(&ssb1, 0xab, sizeof(strstreambuf));
+ memset(&ssb2, 0xab, sizeof(strstreambuf));
+ call_func4(p_strstreambuf_buffer_ctor, &ssb1, buffer, -5, buffer + 20);
+ ok(ssb1.base.allocated == 0, "wrong allocate value, expected 0 got %d\n", ssb1.base.allocated);
+ ok(ssb1.base.unbuffered == 0, "wrong unbuffered value, expected 0 got %d\n", ssb1.base.unbuffered);
+ ok(ssb1.base.base == buffer, "wrong buffer, expected %p got %p\n", buffer, ssb1.base.base);
+ ok(ssb1.base.ebuf == buffer + 0x7fffffff, "wrong buffer end, expected %p + 0x7fffffff got %p\n", buffer, ssb1.base.ebuf);
+ ok(ssb1.base.eback == buffer, "wrong get base, expected %p got %p\n", buffer, ssb1.base.eback);
+ ok(ssb1.base.gptr == buffer, "wrong get pointer, expected %p got %p\n", buffer, ssb1.base.gptr);
+ ok(ssb1.base.egptr == buffer + 20, "wrong get end, expected %p got %p\n", buffer + 20, ssb1.base.egptr);
+ ok(ssb1.base.pbase == buffer + 20, "wrong put base, expected %p got %p\n", buffer + 20, ssb1.base.pbase);
+ ok(ssb1.base.pptr == buffer + 20, "wrong put pointer, expected %p got %p\n", buffer + 20, ssb1.base.pptr);
+ ok(ssb1.base.epptr == buffer + 0x7fffffff, "wrong put end, expected %p + 0x7fffffff got %p\n", buffer, ssb1.base.epptr);
+ ok(ssb1.dynamic == 0, "expected 0, got %d\n", ssb1.dynamic);
+ ok(ssb1.constant == 1, "expected 1, got %d\n", ssb1.constant);
+ call_func1(p_strstreambuf_dtor, &ssb1);
+ call_func1(p_strstreambuf_ctor, &ssb2);
+ ok(ssb2.base.allocated == 0, "wrong allocate value, expected 0 got %d\n", ssb2.base.allocated);
+ ok(ssb2.base.unbuffered == 0, "wrong unbuffered value, expected 0 got %d\n", ssb2.base.unbuffered);
+ ok(ssb2.dynamic == 1, "expected 1, got %d\n", ssb2.dynamic);
+ ok(ssb2.increase == 1, "expected 1, got %d\n", ssb2.increase);
+ ok(ssb2.constant == 0, "expected 0, got %d\n", ssb2.constant);
+ ok(ssb2.f_alloc == NULL, "expected %p, got %p\n", NULL, ssb2.f_alloc);
+ ok(ssb2.f_free == NULL, "expected %p, got %p\n", NULL, ssb2.f_free);
+ call_func1(p_strstreambuf_dtor, &ssb2);
+}
+
struct ios_lock_arg
{
ios *ios_obj;
@@ -1659,6 +1812,7 @@ START_TEST(msvcirt)
test_streambuf();
test_filebuf();
+ test_strstreambuf();
test_ios();
FreeLibrary(msvcrt);
--
2.1.4
More information about the wine-patches
mailing list