From 3b69e28a899bc9739fea1d446b4c0661d0b85bad Mon Sep 17 00:00:00 2001 From: Piotr Caban Date: Wed, 14 Nov 2012 15:37:42 +0100 Subject: [PATCH] msvcp60: Fixed basic_filebuf implementation. --- dlls/msvcp60/ios.c | 250 ++++++++++++++++++--------------------------------- dlls/msvcp60/msvcp.h | 1 + 2 files changed, 88 insertions(+), 163 deletions(-) diff --git a/dlls/msvcp60/ios.c b/dlls/msvcp60/ios.c index b5cdd7e9b4c..5c2a1f45765 100644 --- a/dlls/msvcp60/ios.c +++ b/dlls/msvcp60/ios.c @@ -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) +/* ?_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 %p)\n", this, cvt); + TRACE("(%p)\n", this); - if(codecvt_base_always_noconv(&cvt->base)) { + 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 { - 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) -{ - 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->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) diff --git a/dlls/msvcp60/msvcp.h b/dlls/msvcp60/msvcp.h index 3d1b58e2d40..17cb6eb1294 100644 --- a/dlls/msvcp60/msvcp.h +++ b/dlls/msvcp60/msvcp.h @@ -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 { -- 2.11.4.GIT