msvcp60: Fixed basic_filebuf<short> implementation.

This commit is contained in:
Piotr Caban 2012-11-14 15:37:42 +01:00 committed by Alexandre Julliard
parent 043fcc92be
commit 3b69e28a89
2 changed files with 89 additions and 164 deletions

View File

@ -76,10 +76,11 @@ typedef struct {
typedef struct {
basic_streambuf_wchar base;
codecvt_wchar *cvt;
wchar_t putback;
MSVCP_bool wrotesome;
int state0;
int state;
basic_string_char *str;
MSVCP_bool close;
locale loc;
FILE *file;
} basic_filebuf_wchar;
@ -747,7 +748,7 @@ void __asm_dummy_vtables(void) {
VTABLE_ADD_FUNC(basic_filebuf_wchar_seekpos)
VTABLE_ADD_FUNC(basic_filebuf_wchar_setbuf)
VTABLE_ADD_FUNC(basic_filebuf_wchar_sync)
VTABLE_ADD_FUNC(basic_filebuf_wchar_imbue));
VTABLE_ADD_FUNC(basic_streambuf_wchar_imbue));
__ASM_VTABLE(basic_filebuf_short,
VTABLE_ADD_FUNC(basic_filebuf_wchar_vector_dtor)
VTABLE_ADD_FUNC(basic_filebuf_wchar_overflow)
@ -761,7 +762,7 @@ void __asm_dummy_vtables(void) {
VTABLE_ADD_FUNC(basic_filebuf_wchar_seekpos)
VTABLE_ADD_FUNC(basic_filebuf_short_setbuf)
VTABLE_ADD_FUNC(basic_filebuf_wchar_sync)
VTABLE_ADD_FUNC(basic_filebuf_short_imbue));
VTABLE_ADD_FUNC(basic_streambuf_wchar_imbue));
__ASM_VTABLE(basic_stringbuf_char,
VTABLE_ADD_FUNC(basic_stringbuf_char_vector_dtor)
VTABLE_ADD_FUNC(basic_stringbuf_char_overflow)
@ -2292,6 +2293,15 @@ streamsize __thiscall basic_streambuf_wchar_sputn(basic_streambuf_wchar *this, c
return call_basic_streambuf_wchar_xsputn(this, ptr, count);
}
/* ?getloc@?$basic_streambuf@_WU?$char_traits@_W@std@@@std@@QAE?AVlocale@2@XZ */
/* ?getloc@?$basic_streambuf@_WU?$char_traits@_W@std@@@std@@QEAA?AVlocale@2@XZ */
DEFINE_THISCALL_WRAPPER(basic_streambuf_wchar_getloc, 8)
locale* __thiscall basic_streambuf_wchar_getloc(basic_streambuf_wchar *this, locale *ret)
{
TRACE("(%p %p)\n", this, ret);
return locale_copy_ctor(ret, &this->loc);
}
/* ?_Stinit@?1??_Init@?$basic_filebuf@DU?$char_traits@D@std@@@std@@IAEXPAU_iobuf@@W4_Initfl@23@@Z@4HA */
/* ?_Stinit@?1??_Init@?$basic_filebuf@DU?$char_traits@D@std@@@std@@IEAAXPEAU_iobuf@@W4_Initfl@23@@Z@4HA */
int basic_filebuf_char__Init__Stinit = 0;
@ -2796,8 +2806,9 @@ static void basic_filebuf_wchar__Init(basic_filebuf_wchar *this, FILE *file, bas
TRACE("(%p %p %d)\n", this, file, which);
this->cvt = NULL;
this->wrotesome = FALSE;
this->state = 0;
this->state0 = basic_filebuf_short__Init__Stinit;
this->state = basic_filebuf_short__Init__Stinit;
this->str = NULL;
this->close = (which == INITFL_open);
this->file = file;
@ -2812,68 +2823,29 @@ void __thiscall basic_filebuf_short__Init(basic_filebuf_wchar *this, FILE *file,
TRACE("(%p %p %d)\n", this, file, which);
this->cvt = NULL;
this->wrotesome = FALSE;
this->state0 = basic_filebuf_short__Init__Stinit;
this->state = basic_filebuf_short__Init__Stinit;
this->str = NULL;
this->close = (which == INITFL_open);
this->file = file;
basic_streambuf_wchar__Init_empty(&this->base);
}
/* ?_Initcvt@?$basic_filebuf@_WU?$char_traits@_W@std@@@std@@IAEXPAV?$codecvt@_WDH@2@@Z */
/* ?_Initcvt@?$basic_filebuf@_WU?$char_traits@_W@std@@@std@@IEAAXPEAV?$codecvt@_WDH@2@@Z */
/* ?_Initcvt@?$basic_filebuf@GU?$char_traits@G@std@@@std@@IAEXPAV?$codecvt@GDH@2@@Z */
/* ?_Initcvt@?$basic_filebuf@GU?$char_traits@G@std@@@std@@IEAAXPEAV?$codecvt@GDH@2@@Z */
static void basic_filebuf_wchar__Initcvt(basic_filebuf_wchar *this, codecvt_wchar *cvt)
{
TRACE("(%p %p)\n", this, cvt);
if(codecvt_base_always_noconv(&cvt->base)) {
this->cvt = NULL;
}else {
basic_streambuf_wchar__Init_empty(&this->base);
this->cvt = cvt;
}
}
/* ?_Endwrite@?$basic_filebuf@_WU?$char_traits@_W@std@@@std@@IAE_NXZ */
/* ?_Endwrite@?$basic_filebuf@_WU?$char_traits@_W@std@@@std@@IEAA_NXZ */
/* ?_Endwrite@?$basic_filebuf@GU?$char_traits@G@std@@@std@@IAE_NXZ */
/* ?_Endwrite@?$basic_filebuf@GU?$char_traits@G@std@@@std@@IEAA_NXZ */
static MSVCP_bool basic_filebuf_wchar__Endwrite(basic_filebuf_wchar *this)
/* ?_Initcvt@?$basic_filebuf@GU?$char_traits@G@std@@@std@@IAEXXZ */
/* ?_Initcvt@?$basic_filebuf@GU?$char_traits@G@std@@@std@@IEAAXXZ */
DEFINE_THISCALL_WRAPPER(basic_filebuf_wchar__Initcvt, 4)
void __thiscall basic_filebuf_wchar__Initcvt(basic_filebuf_wchar *this)
{
TRACE("(%p)\n", this);
if(!this->wrotesome || !this->cvt)
return TRUE;
if(call_basic_streambuf_wchar_overflow(&this->base, WEOF) == WEOF)
return FALSE;
while(1) {
/* TODO: check if we need a dynamic buffer here */
char buf[128];
char *next;
int ret;
ret = codecvt_wchar_unshift(this->cvt, &this->state, buf, buf+sizeof(buf), &next);
switch(ret) {
case CODECVT_ok:
this->wrotesome = FALSE;
/* fall through */
case CODECVT_partial:
if(!fwrite(buf, next-buf, 1, this->file))
return FALSE;
if(this->wrotesome)
break;
/* fall through */
case CODECVT_noconv:
if(call_basic_streambuf_wchar_overflow(&this->base, WEOF) == WEOF)
return FALSE;
return TRUE;
default:
return FALSE;
}
this->cvt = codecvt_short_use_facet(&this->base.loc);
locale__Addfac(&this->loc, &this->cvt->base.facet, codecvt_short_id.id, LC_CTYPE);
if(codecvt_base_always_noconv(&this->cvt->base)) {
this->cvt = NULL;
}else {
this->str = MSVCRT_operator_new(sizeof(basic_string_char));
basic_string_char_ctor(this->str);
}
}
@ -2888,15 +2860,9 @@ basic_filebuf_wchar* __thiscall basic_filebuf_wchar_close(basic_filebuf_wchar *t
TRACE("(%p)\n", this);
if(!this->file)
if(!this->file || fclose(this->file))
return NULL;
/* TODO: handle exceptions */
if(!basic_filebuf_wchar__Endwrite(this))
ret = NULL;
if(fclose(this->file))
ret = NULL;
basic_filebuf_wchar__Init(this, NULL, INITFL_close);
return ret;
}
@ -2910,6 +2876,7 @@ static basic_filebuf_wchar* basic_filebuf_wchar_ctor_file(basic_filebuf_wchar *t
basic_streambuf_wchar_ctor(&this->base);
this->base.vtable = &MSVCP_basic_filebuf_wchar_vtable;
locale_ctor(&this->loc);
basic_filebuf_wchar__Init(this, file, INITFL_new);
return this;
}
@ -2924,6 +2891,7 @@ basic_filebuf_wchar* __thiscall basic_filebuf_short_ctor_file(basic_filebuf_wcha
basic_streambuf_short_ctor(&this->base);
this->base.vtable = &MSVCP_basic_filebuf_short_vtable;
locale_ctor(&this->loc);
basic_filebuf_short__Init(this, file, INITFL_new);
return this;
}
@ -2950,8 +2918,9 @@ basic_filebuf_wchar* __thiscall basic_filebuf_short_ctor_uninitialized(basic_fil
{
TRACE("(%p %d)\n", this, uninitialized);
basic_streambuf_short_ctor(&this->base);
basic_streambuf_short_ctor_uninitialized(&this->base, 0);
this->base.vtable = &MSVCP_basic_filebuf_short_vtable;
locale_ctor(&this->loc);
return this;
}
@ -2966,6 +2935,11 @@ void __thiscall basic_filebuf_wchar_dtor(basic_filebuf_wchar *this)
if(this->close)
basic_filebuf_wchar_close(this);
if(this->str) {
basic_string_char_dtor(this->str);
MSVCRT_operator_delete(this->str);
}
locale_dtor(&this->loc);
basic_streambuf_wchar_dtor(&this->base);
}
@ -3017,7 +2991,7 @@ static basic_filebuf_wchar* basic_filebuf_wchar_open_wchar(basic_filebuf_wchar *
return NULL;
basic_filebuf_wchar__Init(this, f, INITFL_open);
basic_filebuf_wchar__Initcvt(this, codecvt_wchar_use_facet(&this->base.loc));
basic_filebuf_wchar__Initcvt(this);
return this;
}
@ -3059,10 +3033,9 @@ basic_filebuf_wchar* __thiscall basic_filebuf_wchar_open_mode(basic_filebuf_wcha
DEFINE_THISCALL_WRAPPER(basic_filebuf_wchar_overflow, 8)
unsigned short __thiscall basic_filebuf_wchar_overflow(basic_filebuf_wchar *this, unsigned short c)
{
char buf[8], *dyn_buf, *to_next;
char *ptr, *to_next;
wchar_t ch = c;
const wchar_t *from_next;
int max_size;
unsigned short ret;
@ -3077,48 +3050,24 @@ unsigned short __thiscall basic_filebuf_wchar_overflow(basic_filebuf_wchar *this
return fwrite(&ch, sizeof(wchar_t), 1, this->file) ? c : WEOF;
from_next = &ch;
do {
ret = codecvt_wchar_out(this->cvt, &this->state, from_next, &ch+1,
&from_next, buf, buf+sizeof(buf), &to_next);
switch(ret) {
case CODECVT_partial:
if(to_next == buf)
break;
/* fall through */
case CODECVT_ok:
if(!fwrite(buf, to_next-buf, 1, this->file))
return WEOF;
if(ret == CODECVT_partial)
continue;
return c;
case CODECVT_noconv:
return fwrite(&ch, sizeof(wchar_t), 1, this->file) ? c : WEOF;
default:
return WEOF;
}
break;
} while(1);
max_size = codecvt_base_max_length(&this->cvt->base);
dyn_buf = malloc(max_size);
if(!dyn_buf)
return WEOF;
ret = codecvt_wchar_out(this->cvt, &this->state, from_next, &ch+1,
&from_next, dyn_buf, dyn_buf+max_size, &to_next);
basic_string_char_clear(this->str);
basic_string_char_append_len_ch(this->str, 8, '\0');
ptr = this->str->ptr;
ret = codecvt_wchar_out(this->cvt, &this->state, &ch, &ch+1, &from_next,
ptr, ptr+basic_string_char_length(this->str), &to_next);
switch(ret) {
case CODECVT_ok:
ret = fwrite(dyn_buf, to_next-dyn_buf, 1, this->file);
free(dyn_buf);
return ret ? c : WEOF;
case CODECVT_partial:
ERR("buffer should be big enough to store all output\n");
if(from_next == &ch)
return WEOF;
/* fall through */
case CODECVT_ok:
if(!fwrite(ptr, to_next-ptr, 1, this->file))
return WEOF;
return c;
case CODECVT_noconv:
return fwrite(&ch, sizeof(wchar_t), 1, this->file) ? c : WEOF;
default:
free(dyn_buf);
return WEOF;
}
}
@ -3139,11 +3088,24 @@ unsigned short __thiscall basic_filebuf_wchar_pbackfail(basic_filebuf_wchar *thi
&& (c==WEOF || basic_streambuf_wchar_gptr(&this->base)[-1]==c)) {
basic_streambuf_wchar__Gndec(&this->base);
return c==WEOF ? !c : c;
}else if(c!=WEOF && !this->cvt) {
}else if(c == WEOF) {
return WEOF;
}else if(!this->cvt) {
return ungetwc(c, this->file);
}else if(c!=WEOF && basic_streambuf_wchar_gptr(&this->base)!=&this->putback) {
this->putback = c;
basic_streambuf_wchar_setg(&this->base, &this->putback, &this->putback, &this->putback+1);
}else if(basic_string_char_length(this->str)) {
char *b, *e, *cur;
e = this->str->ptr;
b = e+this->str->size-1;
for(cur = b; cur>=e; cur--) {
if(ungetc(*cur, this->file) == EOF) {
for(; cur<=b; cur++)
fgetc(this->file);
return WEOF;
}
}
basic_string_char_clear(this->str);
this->state = this->state0;
return c;
}
@ -3158,9 +3120,8 @@ DEFINE_THISCALL_WRAPPER(basic_filebuf_wchar_uflow, 4)
unsigned short __thiscall basic_filebuf_wchar_uflow(basic_filebuf_wchar *this)
{
wchar_t ch, *to_next;
char buf[128];
const char *buf_next;
int c, i;
int c;
TRACE("(%p)\n", this);
@ -3173,35 +3134,28 @@ unsigned short __thiscall basic_filebuf_wchar_uflow(basic_filebuf_wchar *this)
if(!this->cvt)
return fgetwc(this->file);
buf_next = buf;
for(i=0; i < sizeof(buf)/sizeof(buf[0]); i++) {
basic_string_char_clear(this->str);
this->state0 = this->state;
while(1) {
if((c = fgetc(this->file)) == EOF)
return WEOF;
buf[i] = c;
basic_string_char_append_ch(this->str, c);
this->state = this->state0;
switch(codecvt_wchar_in(this->cvt, &this->state, buf_next,
buf+i+1, &buf_next, &ch, &ch+1, &to_next)) {
switch(codecvt_wchar_in(this->cvt, &this->state, this->str->ptr,
this->str->ptr+this->str->size, &buf_next, &ch, &ch+1, &to_next)) {
case CODECVT_partial:
case CODECVT_ok:
if(to_next == &ch)
continue;
for(i--; i>=buf_next-buf; i--)
ungetc(buf[i], this->file);
return ch;
break;
case CODECVT_noconv:
if(i+1 < sizeof(wchar_t))
continue;
memcpy(&ch, buf, sizeof(wchar_t));
return ch;
if(this->str->size < sizeof(unsigned short)/sizeof(char))
break;
return *(unsigned short*)this->str->ptr;
case CODECVT_ok:
return (unsigned short)ch;
default:
return WEOF;
}
}
FIXME("buffer is too small\n");
return WEOF;
}
/* ?underflow@?$basic_filebuf@_WU?$char_traits@_W@std@@@std@@MAEGXZ */
@ -3236,15 +3190,7 @@ fpos_int* __thiscall basic_filebuf_wchar_seekoff(basic_filebuf_wchar *this,
TRACE("(%p %p %ld %d %d)\n", this, ret, off, way, mode);
if(basic_streambuf_wchar_gptr(&this->base) == &this->putback) {
if(way == SEEKDIR_cur)
off -= sizeof(wchar_t);
basic_streambuf_wchar_setg(&this->base, &this->putback, &this->putback+1, &this->putback+1);
}
if(!basic_filebuf_wchar_is_open(this) || !basic_filebuf_wchar__Endwrite(this)
|| fseek(this->file, off, way)) {
if(!basic_filebuf_wchar_is_open(this) || fseek(this->file, off, way)) {
ret->off = -1;
ret->pos = 0;
ret->state = 0;
@ -3270,8 +3216,7 @@ fpos_int* __thiscall basic_filebuf_wchar_seekpos(basic_filebuf_wchar *this,
TRACE("(%p %p %s %d)\n", this, ret, debugstr_fpos_int(&pos), mode);
if(!basic_filebuf_wchar_is_open(this) || !basic_filebuf_wchar__Endwrite(this)
|| fseek(this->file, (LONG)pos.pos, SEEK_SET)
if(!basic_filebuf_wchar_is_open(this) || fseek(this->file, (LONG)pos.pos, SEEK_SET)
|| (pos.off && fseek(this->file, pos.off, SEEK_CUR))) {
ret->off = -1;
ret->pos = 0;
@ -3279,9 +3224,6 @@ fpos_int* __thiscall basic_filebuf_wchar_seekpos(basic_filebuf_wchar *this,
return ret;
}
if(basic_streambuf_wchar_gptr(&this->base) == &this->putback)
basic_streambuf_wchar_setg(&this->base, &this->putback, &this->putback+1, &this->putback+1);
fgetpos(this->file, &fpos);
ret->off = 0;
ret->pos = fpos;
@ -3340,24 +3282,6 @@ int __thiscall basic_filebuf_wchar_sync(basic_filebuf_wchar *this)
return fflush(this->file);
}
/* ?imbue@?$basic_filebuf@_WU?$char_traits@_W@std@@@std@@MAEXABVlocale@2@@Z */
/* ?imbue@?$basic_filebuf@_WU?$char_traits@_W@std@@@std@@MEAAXAEBVlocale@2@@Z */
DEFINE_THISCALL_WRAPPER(basic_filebuf_wchar_imbue, 8)
void __thiscall basic_filebuf_wchar_imbue(basic_filebuf_wchar *this, const locale *loc)
{
TRACE("(%p %p)\n", this, loc);
basic_filebuf_wchar__Initcvt(this, codecvt_wchar_use_facet(loc));
}
/* ?imbue@?$basic_filebuf@GU?$char_traits@G@std@@@std@@MAEXABVlocale@2@@Z */
/* ?imbue@?$basic_filebuf@GU?$char_traits@G@std@@@std@@MEAAXAEBVlocale@2@@Z */
DEFINE_THISCALL_WRAPPER(basic_filebuf_short_imbue, 8)
void __thiscall basic_filebuf_short_imbue(basic_filebuf_wchar *this, const locale *loc)
{
TRACE("(%p %p)\n", this, loc);
basic_filebuf_wchar__Initcvt(this, codecvt_short_use_facet(loc));
}
/* ?_Getstate@?$basic_stringbuf@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AAEHH@Z */
/* ?_Getstate@?$basic_stringbuf@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEAAHH@Z */
static int basic_stringbuf_char__Getstate(basic_stringbuf_char *this, IOSB_openmode mode)

View File

@ -180,6 +180,7 @@ typedef struct {
MSVCP_size_t id;
} locale_id;
extern locale_id codecvt_char_id;
extern locale_id codecvt_short_id;
/* class _Lockit */
typedef struct {