From 27f9052440ac2468f77ee935f2da33b296018693 Mon Sep 17 00:00:00 2001 From: Piotr Caban Date: Fri, 22 Jun 2012 10:27:50 +0200 Subject: [PATCH] msvcp90: Added num_put::put(double) implementation. --- dlls/msvcp90/locale.c | 109 +++++++++++++++++++++++++++++++++++++++-- dlls/msvcp90/msvcp90.h | 2 +- include/msvcrt/stdio.h | 1 + 3 files changed, 107 insertions(+), 5 deletions(-) diff --git a/dlls/msvcp90/locale.c b/dlls/msvcp90/locale.c index 2e48c791a0e..88f02e397bf 100644 --- a/dlls/msvcp90/locale.c +++ b/dlls/msvcp90/locale.c @@ -5458,8 +5458,32 @@ ostreambuf_iterator_char* __cdecl num_put_char__Rep(const num_put *this, ostream /* ?_Ffmt@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@AEBAPEADPEADDH@Z */ char* __cdecl num_put_char__Ffmt(const num_put *this, char *fmt, char spec, int fmtfl) { - FIXME("(%p %p %d %d) stub\n", this, fmt, spec, fmtfl); - return NULL; + int type = fmtfl & FMTFLAG_floatfield; + char *p = fmt; + + TRACE("(%p %p %d %d)\n", this, fmt, spec, fmtfl); + + *p++ = '%'; + if(fmtfl & FMTFLAG_showpos) + *p++ = '+'; + if(fmtfl & FMTFLAG_showbase) + *p++ = '#'; + *p++ = '.'; + *p++ = '*'; + if(spec) + *p++ = spec; + + if(type == FMTFLAG_fixed) + *p++ = 'f'; + else if(type == FMTFLAG_scientific) + *p++ = (fmtfl & FMTFLAG_uppercase) ? 'E' : 'e'; + else if(type == (FMTFLAG_fixed|FMTFLAG_scientific)) + *p++ = (fmtfl & FMTFLAG_uppercase) ? 'A' : 'a'; + else + *p++ = (fmtfl & FMTFLAG_uppercase) ? 'G' : 'g'; + + *p++ = '\0'; + return fmt; } /* ?_Fput@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@DPBDIIII@Z */ @@ -5473,6 +5497,67 @@ ostreambuf_iterator_char* __cdecl num_put_char__Fput(const num_put *this, ostrea return NULL; } +/* TODO: This function should be removed when num_put_char__Fput is implemented */ +static ostreambuf_iterator_char* num_put_char_fput(const num_put *this, ostreambuf_iterator_char *ret, + ostreambuf_iterator_char dest, ios_base *base, char fill, char *buf, MSVCP_size_t count) +{ + numpunct_char *numpunct = numpunct_char_use_facet(base->loc); + basic_string_char grouping_bstr; + const char *grouping; + char *p, sep = *localeconv()->decimal_point; + int cur_group = 0, group_size = 0; + int adjustfield = base->fmtfl & FMTFLAG_adjustfield; + MSVCP_size_t pad; + + TRACE("(%p %p %p %d %s %ld)\n", this, ret, base, fill, buf, count); + + /* Change decimal point */ + for(p=buf; pbuf && sep && grouping[cur_group]!=CHAR_MAX; p--) { + group_size++; + if(group_size == grouping[cur_group]) { + group_size = 0; + if(grouping[cur_group+1]) + cur_group++; + + memmove(p+1, p, buf+count-p); + *p = sep; + count++; + } + } + MSVCP_basic_string_char_dtor(&grouping_bstr); + + /* Display number with padding */ + if(count >= base->wide) + pad = 0; + else + pad = base->wide-count; + base->wide = 0; + + if((adjustfield & FMTFLAG_internal) && (buf[0]=='-' || buf[0]=='+')) { + num_put_char__Putc(this, &dest, dest, buf, 1); + buf++; + } + if(adjustfield != FMTFLAG_left) { + num_put_char__Rep(this, ret, dest, fill, pad); + pad = 0; + } + num_put_char__Putc(this, &dest, dest, buf, count); + return num_put_char__Rep(this, ret, dest, fill, pad); +} + /* ?_Ifmt@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@ABAPADPADPBDH@Z */ /* ?_Ifmt@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@AEBAPEADPEADPEBDH@Z */ char* __cdecl num_put_char__Ifmt(const num_put *this, char *fmt, const char *spec, int fmtfl) @@ -5629,8 +5714,24 @@ DEFINE_THISCALL_WRAPPER(num_put_char_do_put_double, 32) ostreambuf_iterator_char* __thiscall num_put_char_do_put_double(const num_put *this, ostreambuf_iterator_char *ret, ostreambuf_iterator_char dest, ios_base *base, char fill, double v) { - FIXME("(%p %p %p %d %lf) stub\n", this, ret, base, fill, v); - return NULL; + char *tmp; + char fmt[8]; /* strlen("%+#.*lg")+1 */ + int size; + + TRACE("(%p %p %p %d %lf)\n", this, ret, base, fill, v); + + num_put_char__Ffmt(this, fmt, '\0', base->fmtfl); + size = _scprintf(fmt, base->prec, v); + + /* TODO: don't use dynamic allocation */ + tmp = MSVCRT_operator_new(size*2); + if(!tmp) { + ERR("Out of memory\n"); + throw_exception(EXCEPTION_BAD_ALLOC, NULL); + } + num_put_char_fput(this, ret, dest, base, fill, tmp, sprintf(tmp, fmt, base->prec, v)); + MSVCRT_operator_delete(tmp); + return ret; } /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@DN@Z */ diff --git a/dlls/msvcp90/msvcp90.h b/dlls/msvcp90/msvcp90.h index edb3efa33d2..cc7a2aa073e 100644 --- a/dlls/msvcp90/msvcp90.h +++ b/dlls/msvcp90/msvcp90.h @@ -417,7 +417,7 @@ typedef enum { FMTFLAG_stdio = 0x8000, FMTFLAG_adjustfield = FMTFLAG_left|FMTFLAG_right|FMTFLAG_internal, FMTFLAG_basefield = FMTFLAG_dec|FMTFLAG_oct|FMTFLAG_hex, - FMTFLAG_floadfield = FMTFLAG_scientific|FMTFLAG_fixed, + FMTFLAG_floatfield = FMTFLAG_scientific|FMTFLAG_fixed, FMTFLAG_mask = 0xffff } IOSB_fmtflags; diff --git a/include/msvcrt/stdio.h b/include/msvcrt/stdio.h index e2c1669de3f..80439ee0b33 100644 --- a/include/msvcrt/stdio.h +++ b/include/msvcrt/stdio.h @@ -167,6 +167,7 @@ void __cdecl setbuf(FILE*,char*); int __cdecl setvbuf(FILE*,char*,int,size_t); int __cdecl sprintf(char*,const char*,...); int __cdecl sprintf_s(char*,size_t,const char*,...); +int __cdecl _scprintf(const char *, ...); int __cdecl sscanf(const char*,const char*,...); int __cdecl sscanf_s(const char*,const char*,...); FILE* __cdecl tmpfile(void);