From 4c357de5d326c178de54d6084dd50ee01de6e153 Mon Sep 17 00:00:00 2001 From: Daniel Lehman Date: Thu, 11 Oct 2012 14:21:49 -0700 Subject: [PATCH] msvcp: Sync num_get<>::_Getifld. --- dlls/msvcp100/locale.c | 156 +++++++++++++++++++++++---------------- dlls/msvcp100/msvcp.h | 2 + dlls/msvcp100/string.c | 53 ++++++++++++++ dlls/msvcp60/locale.c | 162 ++++++++++++++++++++++++----------------- dlls/msvcp71/locale.c | 156 +++++++++++++++++++++++---------------- 5 files changed, 337 insertions(+), 192 deletions(-) diff --git a/dlls/msvcp100/locale.c b/dlls/msvcp100/locale.c index 304f1983027..51a37d5c703 100644 --- a/dlls/msvcp100/locale.c +++ b/dlls/msvcp100/locale.c @@ -3976,10 +3976,11 @@ static int num_get__Getifld(const num_get *this, char *dest, istreambuf_iterator { wchar_t digits[23], *digits_pos, sep; basic_string_char grouping_bstr; + basic_string_char groups_found; int i, basefield, base, groups_no = 0, cur_group = 0; - char *dest_beg = dest, *dest_end = dest+24, *groups = NULL; - const char *grouping; - BOOL error = TRUE, dest_empty = TRUE; + char *dest_beg = dest, *dest_end = dest+24; + const char *grouping, *groups; + BOOL error = TRUE, dest_empty = TRUE, found_zero = FALSE; TRACE("(%p %p %p %04x %p)\n", dest, first, last, fmtflags, loc); @@ -4013,46 +4014,48 @@ static int num_get__Getifld(const num_get *this, char *dest, istreambuf_iterator istreambuf_iterator_wchar_inc(first); } - if(!base && first->strbuf && first->val==digits[0]) { + if(first->strbuf && first->val==digits[0]) { + found_zero = TRUE; istreambuf_iterator_wchar_inc(first); - if(first->strbuf && (first->val==mb_to_wc('x', &this->cvt) || first->val==mb_to_wc('x', &this->cvt))) { - istreambuf_iterator_wchar_inc(first); - base = 22; + if(first->strbuf && (first->val==mb_to_wc('x', &this->cvt) || first->val==mb_to_wc('X', &this->cvt))) { + if(!base || base == 22) { + found_zero = FALSE; + istreambuf_iterator_wchar_inc(first); + base = 22; + }else { + base = 10; + } }else { error = FALSE; - base = 8; + if(!base) base = 8; } }else { - base = 10; + if(!base) base = 10; } digits[base] = 0; if(sep) { - groups_no = strlen(grouping)+2; - groups = calloc(groups_no, sizeof(char)); + MSVCP_basic_string_char_ctor(&groups_found); + if(found_zero) ++groups_no; } for(; first->strbuf; istreambuf_iterator_wchar_inc(first)) { if(!(digits_pos = wcschr(digits, first->val))) { if(sep && first->val==sep) { - if(cur_group == groups_no+1) { - if(groups[1] != groups[2]) { - error = TRUE; - break; - }else { - memmove(groups+1, groups+2, groups_no); - groups[cur_group] = 0; - } - }else { - cur_group++; - } + if(!groups_no) break; /* empty group - stop parsing */ + MSVCP_basic_string_char_append_ch(&groups_found, groups_no); + groups_no = 0; + ++cur_group; }else { break; } }else { error = FALSE; - if(dest_empty && first->val == digits[0]) + if(dest_empty && first->val == digits[0]) { + found_zero = TRUE; + ++groups_no; continue; + } dest_empty = FALSE; /* skip digits that can't be copied to dest buffer, other * functions are responsible for detecting overflows */ @@ -4060,14 +4063,20 @@ static int num_get__Getifld(const num_get *this, char *dest, istreambuf_iterator *dest++ = (digits_pos-digits<10 ? '0'+digits_pos-digits : (digits_pos-digits<16 ? 'a'+digits_pos-digits-10 : 'A'+digits_pos-digits-16)); - if(sep && groups[cur_group]=0 && !error; cur_group--) { @@ -4083,12 +4092,17 @@ static int num_get__Getifld(const num_get *this, char *dest, istreambuf_iterator grouping++; } } - MSVCP_basic_string_char_dtor(&grouping_bstr); - free(groups); - if(error) - dest = dest_beg; - else if(dest_empty) + MSVCP_basic_string_char_dtor(&grouping_bstr); + if(sep) + MSVCP_basic_string_char_dtor(&groups_found); + + if(error) { + if (found_zero) + *dest++ = '0'; + else + dest = dest_beg; + }else if(dest_empty) *dest++ = '0'; *dest = '\0'; @@ -5067,10 +5081,11 @@ int __cdecl num_get_char__Getifld(const num_get *this, char *dest, istreambuf_it numpunct_char *numpunct = numpunct_char_use_facet(loc); basic_string_char grouping_bstr; + basic_string_char groups_found; int basefield, base, groups_no = 0, cur_group = 0; - char *dest_beg = dest, *dest_end = dest+24, *groups = NULL, sep; - const char *grouping; - BOOL error = TRUE, dest_empty = TRUE; + char *dest_beg = dest, *dest_end = dest+24, sep; + const char *grouping, *groups; + BOOL error = TRUE, dest_empty = TRUE, found_zero = FALSE; TRACE("(%p %p %p %04x %p)\n", dest, first, last, fmtflags, loc); @@ -5094,58 +5109,68 @@ int __cdecl num_get_char__Getifld(const num_get *this, char *dest, istreambuf_it istreambuf_iterator_char_inc(first); } - if(!base && first->strbuf && first->val=='0') { + if(first->strbuf && first->val=='0') { + found_zero = TRUE; istreambuf_iterator_char_inc(first); if(first->strbuf && (first->val=='x' || first->val=='X')) { - istreambuf_iterator_char_inc(first); - base = 22; + if(!base || base == 22) { + found_zero = FALSE; + istreambuf_iterator_char_inc(first); + base = 22; + }else { + base = 10; + } }else { error = FALSE; - base = 8; + if(!base) base = 8; } }else { - base = 10; + if (!base) base = 10; } - if(sep) { - groups_no = strlen(grouping)+2; - groups = calloc(groups_no, sizeof(char)); + if(sep) + { + MSVCP_basic_string_char_ctor(&groups_found); + if(found_zero) ++groups_no; } for(; first->strbuf; istreambuf_iterator_char_inc(first)) { if(!memchr(digits, first->val, base)) { if(sep && first->val==sep) { - if(cur_group == groups_no+1) { - if(groups[1] != groups[2]) { - error = TRUE; - break; - }else { - memmove(groups+1, groups+2, groups_no); - groups[cur_group] = 0; - } - }else { - cur_group++; - } + if(!groups_no) break; /* empty group - stop parsing */ + MSVCP_basic_string_char_append_ch(&groups_found, groups_no); + groups_no = 0; + ++cur_group; }else { break; } }else { error = FALSE; if(dest_empty && first->val == '0') + { + found_zero = TRUE; + ++groups_no; continue; + } dest_empty = FALSE; /* skip digits that can't be copied to dest buffer, other * functions are responsible for detecting overflows */ if(dest < dest_end) *dest++ = first->val; - if(sep && groups[cur_group]=0 && !error; cur_group--) { @@ -5161,12 +5186,17 @@ int __cdecl num_get_char__Getifld(const num_get *this, char *dest, istreambuf_it grouping++; } } - MSVCP_basic_string_char_dtor(&grouping_bstr); - free(groups); - if(error) - dest = dest_beg; - else if(dest_empty) + MSVCP_basic_string_char_dtor(&grouping_bstr); + if(sep) + MSVCP_basic_string_char_dtor(&groups_found); + + if(error) { + if (found_zero) + *dest++ = '0'; + else + dest = dest_beg; + }else if(dest_empty) *dest++ = '0'; *dest = '\0'; diff --git a/dlls/msvcp100/msvcp.h b/dlls/msvcp100/msvcp.h index a03bbd4e13f..571c2d06640 100644 --- a/dlls/msvcp100/msvcp.h +++ b/dlls/msvcp100/msvcp.h @@ -48,10 +48,12 @@ typedef struct MSVCP_size_t res; } basic_string_char; +basic_string_char* MSVCP_basic_string_char_ctor(basic_string_char*); basic_string_char* MSVCP_basic_string_char_ctor_cstr(basic_string_char*, const char*); basic_string_char* MSVCP_basic_string_char_copy_ctor(basic_string_char*, const basic_string_char*); void MSVCP_basic_string_char_dtor(basic_string_char*); const char* MSVCP_basic_string_char_c_str(const basic_string_char*); +basic_string_char* MSVCP_basic_string_char_append_ch(basic_string_char*, char); MSVCP_size_t MSVCP_basic_string_char_length(const basic_string_char*); #define BUF_SIZE_WCHAR 8 diff --git a/dlls/msvcp100/string.c b/dlls/msvcp100/string.c index 9ce7d38d0cb..b1b6b891031 100644 --- a/dlls/msvcp100/string.c +++ b/dlls/msvcp100/string.c @@ -38,6 +38,13 @@ static void MSVCP_char_traits_char_assign(char *ch, const char *assign) *ch = *assign; } +/* ?assign@?$char_traits@D@std@@SAPADPADID@Z */ +/* ?assign@?$char_traits@D@std@@SAPEADPEAD_KD@Z */ +static char* MSVCP_char_traits_char_assignn(char *str, MSVCP_size_t num, char c) +{ + return memset(str, c, num); +} + /* ?length@?$char_traits@D@std@@SAIPBD@Z */ /* ?length@?$char_traits@D@std@@SA_KPEBD@Z */ static MSVCP_size_t MSVCP_char_traits_char_length(const char *str) @@ -121,6 +128,16 @@ static wchar_t* MSVCP_char_traits_wchar__Move_s(wchar_t *dest, return memmove(dest, src, count * sizeof(WCHAR)); } +/* _String_base */ +/* ?_Xlen@_String_base@std@@SAXXZ */ +static void MSVCP__String_base_Xlen(void) +{ + static const char msg[] = "string too long"; + + TRACE("\n"); + throw_exception(EXCEPTION_LENGTH_ERROR, msg); +} + /* _String_base */ /* ?_Xran@_String_base@std@@SAXXZ */ static void MSVCP__String_base_Xran(void) @@ -340,6 +357,16 @@ basic_string_char* MSVCP_basic_string_char_copy_ctor( return this; } +/* ??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ */ +/* ??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAA@XZ */ +basic_string_char* MSVCP_basic_string_char_ctor(basic_string_char *this) +{ + TRACE("%p\n", this); + + basic_string_char_tidy(this, FALSE, 0); + return this; +} + /* ??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@PBD@Z */ /* ??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAA@PEBD@Z */ basic_string_char* MSVCP_basic_string_char_ctor_cstr( @@ -370,6 +397,32 @@ MSVCP_size_t MSVCP_basic_string_char_length(const basic_string_char *this) return this->size; } +/* ?append@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAEAAV12@ID@Z */ +/* ?append@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAAAEAV12@_KD@Z */ +basic_string_char* MSVCP_basic_string_char_append_len_ch(basic_string_char *this, MSVCP_size_t count, char ch) +{ + TRACE("%p %lu %c\n", this, count, ch); + + if(MSVCP_basic_string_char_npos-this->size <= count) + MSVCP__String_base_Xlen(); + + if(basic_string_char_grow(this, this->size+count, FALSE)) { + MSVCP_char_traits_char_assignn(basic_string_char_ptr(this)+this->size, count, ch); + basic_string_char_eos(this, this->size+count); + } + + return this; +} + +/* ??Y?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAEAAV01@D@Z */ +/* ??Y?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAAAEAV01@D@Z */ +/* ?push_back@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAEXD@Z */ +/* ?push_back@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAAXD@Z */ +basic_string_char* MSVCP_basic_string_char_append_ch(basic_string_char *this, char ch) +{ + return MSVCP_basic_string_char_append_len_ch(this, 1, ch); +} + /* basic_string, allocator> */ /* basic_string, allocator> */ /* ?npos@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@2IB */ diff --git a/dlls/msvcp60/locale.c b/dlls/msvcp60/locale.c index fc1f0ecf0a1..e65ce122a3b 100644 --- a/dlls/msvcp60/locale.c +++ b/dlls/msvcp60/locale.c @@ -4116,10 +4116,11 @@ static int num_get__Getifld(const num_get *this, char *dest, istreambuf_iterator { wchar_t digits[23], *digits_pos, sep; basic_string_char grouping_bstr; + basic_string_char groups_found; int i, basefield, base, groups_no = 0, cur_group = 0; - char *dest_beg = dest, *dest_end = dest+24, *groups = NULL; - const char *grouping; - BOOL error = TRUE, dest_empty = TRUE; + char *dest_beg = dest, *dest_end = dest+24; + const char *grouping, *groups; + BOOL error = TRUE, dest_empty = TRUE, found_zero = FALSE; TRACE("(%p %p %p %04x %p)\n", dest, first, last, fmtflags, loc); @@ -4132,7 +4133,7 @@ static int num_get__Getifld(const num_get *this, char *dest, istreambuf_iterator numpunct_wchar_grouping(numpunct, &grouping_bstr); grouping = basic_string_char_c_str(&grouping_bstr); - sep = grouping[0] ? numpunct_wchar_thousands_sep(numpunct) : '\0'; + sep = grouping ? numpunct_wchar_thousands_sep(numpunct) : '\0'; basefield = fmtflags & FMTFLAG_basefield; if(basefield == FMTFLAG_oct) @@ -4153,46 +4154,48 @@ static int num_get__Getifld(const num_get *this, char *dest, istreambuf_iterator istreambuf_iterator_wchar_inc(first); } - if(!base && first->strbuf && first->val==digits[0]) { + if(first->strbuf && first->val==digits[0]) { + found_zero = TRUE; istreambuf_iterator_wchar_inc(first); - if(first->strbuf && (first->val==mb_to_wc('x', &this->cvt) || first->val==mb_to_wc('x', &this->cvt))) { - istreambuf_iterator_wchar_inc(first); - base = 22; + if(first->strbuf && (first->val==mb_to_wc('x', &this->cvt) || first->val==mb_to_wc('X', &this->cvt))) { + if(!base || base == 22) { + found_zero = FALSE; + istreambuf_iterator_wchar_inc(first); + base = 22; + }else { + base = 10; + } }else { error = FALSE; - base = 8; + if(!base) base = 8; } }else { - base = 10; + if(!base) base = 10; } digits[base] = 0; if(sep) { - groups_no = strlen(grouping)+2; - groups = calloc(groups_no, sizeof(char)); + basic_string_char_ctor(&groups_found); + if(found_zero) ++groups_no; } for(; first->strbuf; istreambuf_iterator_wchar_inc(first)) { if(!(digits_pos = wcschr(digits, first->val))) { if(sep && first->val==sep) { - if(cur_group == groups_no+1) { - if(groups[1] != groups[2]) { - error = TRUE; - break; - }else { - memmove(groups+1, groups+2, groups_no); - groups[cur_group] = 0; - } - }else { - cur_group++; - } + if(!groups_no) break; /* empty group - stop parsing */ + basic_string_char_append_ch(&groups_found, groups_no); + groups_no = 0; + ++cur_group; }else { break; } }else { error = FALSE; - if(dest_empty && first->val == digits[0]) + if(dest_empty && first->val == digits[0]) { + found_zero = TRUE; + ++groups_no; continue; + } dest_empty = FALSE; /* skip digits that can't be copied to dest buffer, other * functions are responsible for detecting overflows */ @@ -4200,14 +4203,20 @@ static int num_get__Getifld(const num_get *this, char *dest, istreambuf_iterator *dest++ = (digits_pos-digits<10 ? '0'+digits_pos-digits : (digits_pos-digits<16 ? 'a'+digits_pos-digits-10 : 'A'+digits_pos-digits-16)); - if(sep && groups[cur_group]=0 && !error; cur_group--) { @@ -4223,12 +4232,17 @@ static int num_get__Getifld(const num_get *this, char *dest, istreambuf_iterator grouping++; } } - basic_string_char_dtor(&grouping_bstr); - free(groups); - if(error) - dest = dest_beg; - else if(dest_empty) + basic_string_char_dtor(&grouping_bstr); + if(sep) + basic_string_char_dtor(&groups_found); + + if(error) { + if (found_zero) + *dest++ = '0'; + else + dest = dest_beg; + }else if(dest_empty) *dest++ = '0'; *dest = '\0'; @@ -5177,10 +5191,11 @@ static int num_get_char__Getifld(const num_get *this, char *dest, istreambuf_ite numpunct_char *numpunct = numpunct_char_use_facet(loc); basic_string_char grouping_bstr; + basic_string_char groups_found; int basefield, base, groups_no = 0, cur_group = 0; - char *dest_beg = dest, *dest_end = dest+24, *groups = NULL, sep; - const char *grouping; - BOOL error = TRUE, dest_empty = TRUE; + char *dest_beg = dest, *dest_end = dest+24, sep; + const char *grouping, *groups; + BOOL error = TRUE, dest_empty = TRUE, found_zero = FALSE; TRACE("(%p %p %p %04x %p)\n", dest, first, last, fmtflags, loc); @@ -5204,58 +5219,68 @@ static int num_get_char__Getifld(const num_get *this, char *dest, istreambuf_ite istreambuf_iterator_char_inc(first); } - if(!base && first->strbuf && first->val=='0') { + if(first->strbuf && first->val=='0') { + found_zero = TRUE; istreambuf_iterator_char_inc(first); if(first->strbuf && (first->val=='x' || first->val=='X')) { - istreambuf_iterator_char_inc(first); - base = 22; + if(!base || base == 22) { + found_zero = FALSE; + istreambuf_iterator_char_inc(first); + base = 22; + }else { + base = 10; + } }else { error = FALSE; - base = 8; + if(!base) base = 8; } }else { - base = 10; + if (!base) base = 10; } - if(sep) { - groups_no = strlen(grouping)+2; - groups = calloc(groups_no, sizeof(char)); + if(sep) + { + basic_string_char_ctor(&groups_found); + if(found_zero) ++groups_no; } for(; first->strbuf; istreambuf_iterator_char_inc(first)) { if(!memchr(digits, first->val, base)) { if(sep && first->val==sep) { - if(cur_group == groups_no+1) { - if(groups[1] != groups[2]) { - error = TRUE; - break; - }else { - memmove(groups+1, groups+2, groups_no); - groups[cur_group] = 0; - } - }else { - cur_group++; - } + if(!groups_no) break; /* empty group - stop parsing */ + basic_string_char_append_ch(&groups_found, groups_no); + groups_no = 0; + ++cur_group; }else { break; } }else { error = FALSE; if(dest_empty && first->val == '0') + { + found_zero = TRUE; + ++groups_no; continue; + } dest_empty = FALSE; /* skip digits that can't be copied to dest buffer, other * functions are responsible for detecting overflows */ if(dest < dest_end) *dest++ = first->val; - if(sep && groups[cur_group]=0 && !error; cur_group--) { @@ -5271,12 +5296,17 @@ static int num_get_char__Getifld(const num_get *this, char *dest, istreambuf_ite grouping++; } } - basic_string_char_dtor(&grouping_bstr); - free(groups); - if(error) - dest = dest_beg; - else if(dest_empty) + basic_string_char_dtor(&grouping_bstr); + if(sep) + basic_string_char_dtor(&groups_found); + + if(error) { + if (found_zero) + *dest++ = '0'; + else + dest = dest_beg; + }else if(dest_empty) *dest++ = '0'; *dest = '\0'; diff --git a/dlls/msvcp71/locale.c b/dlls/msvcp71/locale.c index 3a5227184bc..d13aa21ccf7 100644 --- a/dlls/msvcp71/locale.c +++ b/dlls/msvcp71/locale.c @@ -4399,10 +4399,11 @@ static int num_get__Getifld(const num_get *this, char *dest, istreambuf_iterator { wchar_t digits[23], *digits_pos, sep; basic_string_char grouping_bstr; + basic_string_char groups_found; int i, basefield, base, groups_no = 0, cur_group = 0; - char *dest_beg = dest, *dest_end = dest+24, *groups = NULL; - const char *grouping; - BOOL error = TRUE, dest_empty = TRUE; + char *dest_beg = dest, *dest_end = dest+24; + const char *grouping, *groups; + BOOL error = TRUE, dest_empty = TRUE, found_zero = FALSE; TRACE("(%p %p %p %04x %p)\n", dest, first, last, fmtflags, loc); @@ -4436,46 +4437,48 @@ static int num_get__Getifld(const num_get *this, char *dest, istreambuf_iterator istreambuf_iterator_wchar_inc(first); } - if(!base && first->strbuf && first->val==digits[0]) { + if(first->strbuf && first->val==digits[0]) { + found_zero = TRUE; istreambuf_iterator_wchar_inc(first); - if(first->strbuf && (first->val==mb_to_wc('x', &this->cvt) || first->val==mb_to_wc('x', &this->cvt))) { - istreambuf_iterator_wchar_inc(first); - base = 22; + if(first->strbuf && (first->val==mb_to_wc('x', &this->cvt) || first->val==mb_to_wc('X', &this->cvt))) { + if(!base || base == 22) { + found_zero = FALSE; + istreambuf_iterator_wchar_inc(first); + base = 22; + }else { + base = 10; + } }else { error = FALSE; - base = 8; + if(!base) base = 8; } }else { - base = 10; + if(!base) base = 10; } digits[base] = 0; if(sep) { - groups_no = strlen(grouping)+2; - groups = calloc(groups_no, sizeof(char)); + MSVCP_basic_string_char_ctor(&groups_found); + if(found_zero) ++groups_no; } for(; first->strbuf; istreambuf_iterator_wchar_inc(first)) { if(!(digits_pos = wcschr(digits, first->val))) { if(sep && first->val==sep) { - if(cur_group == groups_no+1) { - if(groups[1] != groups[2]) { - error = TRUE; - break; - }else { - memmove(groups+1, groups+2, groups_no); - groups[cur_group] = 0; - } - }else { - cur_group++; - } + if(!groups_no) break; /* empty group - stop parsing */ + MSVCP_basic_string_char_append_ch(&groups_found, groups_no); + groups_no = 0; + ++cur_group; }else { break; } }else { error = FALSE; - if(dest_empty && first->val == digits[0]) + if(dest_empty && first->val == digits[0]) { + found_zero = TRUE; + ++groups_no; continue; + } dest_empty = FALSE; /* skip digits that can't be copied to dest buffer, other * functions are responsible for detecting overflows */ @@ -4483,14 +4486,20 @@ static int num_get__Getifld(const num_get *this, char *dest, istreambuf_iterator *dest++ = (digits_pos-digits<10 ? '0'+digits_pos-digits : (digits_pos-digits<16 ? 'a'+digits_pos-digits-10 : 'A'+digits_pos-digits-16)); - if(sep && groups[cur_group]=0 && !error; cur_group--) { @@ -4506,12 +4515,17 @@ static int num_get__Getifld(const num_get *this, char *dest, istreambuf_iterator grouping++; } } - MSVCP_basic_string_char_dtor(&grouping_bstr); - free(groups); - if(error) - dest = dest_beg; - else if(dest_empty) + MSVCP_basic_string_char_dtor(&grouping_bstr); + if(sep) + MSVCP_basic_string_char_dtor(&groups_found); + + if(error) { + if (found_zero) + *dest++ = '0'; + else + dest = dest_beg; + }else if(dest_empty) *dest++ = '0'; *dest = '\0'; @@ -5470,10 +5484,11 @@ int __cdecl num_get_char__Getifld(const num_get *this, char *dest, istreambuf_it numpunct_char *numpunct = numpunct_char_use_facet(loc); basic_string_char grouping_bstr; + basic_string_char groups_found; int basefield, base, groups_no = 0, cur_group = 0; - char *dest_beg = dest, *dest_end = dest+24, *groups = NULL, sep; - const char *grouping; - BOOL error = TRUE, dest_empty = TRUE; + char *dest_beg = dest, *dest_end = dest+24, sep; + const char *grouping, *groups; + BOOL error = TRUE, dest_empty = TRUE, found_zero = FALSE; TRACE("(%p %p %p %04x %p)\n", dest, first, last, fmtflags, loc); @@ -5497,58 +5512,68 @@ int __cdecl num_get_char__Getifld(const num_get *this, char *dest, istreambuf_it istreambuf_iterator_char_inc(first); } - if(!base && first->strbuf && first->val=='0') { + if(first->strbuf && first->val=='0') { + found_zero = TRUE; istreambuf_iterator_char_inc(first); if(first->strbuf && (first->val=='x' || first->val=='X')) { - istreambuf_iterator_char_inc(first); - base = 22; + if(!base || base == 22) { + found_zero = FALSE; + istreambuf_iterator_char_inc(first); + base = 22; + }else { + base = 10; + } }else { error = FALSE; - base = 8; + if(!base) base = 8; } }else { - base = 10; + if (!base) base = 10; } - if(sep) { - groups_no = strlen(grouping)+2; - groups = calloc(groups_no, sizeof(char)); + if(sep) + { + MSVCP_basic_string_char_ctor(&groups_found); + if(found_zero) ++groups_no; } for(; first->strbuf; istreambuf_iterator_char_inc(first)) { if(!memchr(digits, first->val, base)) { if(sep && first->val==sep) { - if(cur_group == groups_no+1) { - if(groups[1] != groups[2]) { - error = TRUE; - break; - }else { - memmove(groups+1, groups+2, groups_no); - groups[cur_group] = 0; - } - }else { - cur_group++; - } + if(!groups_no) break; /* empty group - stop parsing */ + MSVCP_basic_string_char_append_ch(&groups_found, groups_no); + groups_no = 0; + ++cur_group; }else { break; } }else { error = FALSE; if(dest_empty && first->val == '0') + { + found_zero = TRUE; + ++groups_no; continue; + } dest_empty = FALSE; /* skip digits that can't be copied to dest buffer, other * functions are responsible for detecting overflows */ if(dest < dest_end) *dest++ = first->val; - if(sep && groups[cur_group]=0 && !error; cur_group--) { @@ -5564,12 +5589,17 @@ int __cdecl num_get_char__Getifld(const num_get *this, char *dest, istreambuf_it grouping++; } } - MSVCP_basic_string_char_dtor(&grouping_bstr); - free(groups); - if(error) - dest = dest_beg; - else if(dest_empty) + MSVCP_basic_string_char_dtor(&grouping_bstr); + if(sep) + MSVCP_basic_string_char_dtor(&groups_found); + + if(error) { + if (found_zero) + *dest++ = '0'; + else + dest = dest_beg; + }else if(dest_empty) *dest++ = '0'; *dest = '\0';