msvcp: Sync num_get<>::_Getifld.

This commit is contained in:
Daniel Lehman 2012-10-11 14:21:49 -07:00 committed by Alexandre Julliard
parent c99a19208a
commit 4c357de5d3
5 changed files with 337 additions and 192 deletions

View File

@ -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]<CHAR_MAX)
groups[cur_group]++;
if(sep && groups_no<CHAR_MAX)
++groups_no;
}
}
if(sep && groups_no)
MSVCP_basic_string_char_append_ch(&groups_found, groups_no);
groups = MSVCP_basic_string_char_c_str(&groups_found);
if(cur_group && !groups[cur_group])
error = TRUE;
else if(!cur_group)
{
error = TRUE; /* trailing empty */
found_zero = FALSE;
}else if(!cur_group) /* no groups, skip loop */
cur_group--;
for(; 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]<CHAR_MAX)
groups[cur_group]++;
if(sep && groups_no<CHAR_MAX)
++groups_no;
}
}
if(sep && groups_no)
MSVCP_basic_string_char_append_ch(&groups_found, groups_no);
groups = MSVCP_basic_string_char_c_str(&groups_found);
if(cur_group && !groups[cur_group])
error = TRUE;
else if(!cur_group)
{
error = TRUE; /* trailing empty */
found_zero = FALSE;
}else if(!cur_group) /* no groups, skip loop */
cur_group--;
for(; 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';

View File

@ -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

View File

@ -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<wchar_t, char_traits<wchar_t>, allocator<wchar_t>> */
/* basic_string<unsigned short, char_traits<unsigned short>, allocator<unsigned short>> */
/* ?npos@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@2IB */

View File

@ -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]<CHAR_MAX)
groups[cur_group]++;
if(sep && groups_no<CHAR_MAX)
++groups_no;
}
}
if(cur_group && !groups[cur_group])
error = TRUE;
else if(!cur_group)
if(sep && groups_no)
basic_string_char_append_ch(&groups_found, groups_no);
groups = basic_string_char_c_str(&groups_found);
if(cur_group && groups && !groups[cur_group])
{
error = TRUE; /* trailing empty */
found_zero = FALSE;
}else if(!cur_group) /* no groups, skip loop */
cur_group--;
for(; 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]<CHAR_MAX)
groups[cur_group]++;
if(sep && groups_no<CHAR_MAX)
++groups_no;
}
}
if(cur_group && !groups[cur_group])
error = TRUE;
else if(!cur_group)
if(sep && groups_no)
basic_string_char_append_ch(&groups_found, groups_no);
groups = basic_string_char_c_str(&groups_found);
if(cur_group && groups && !groups[cur_group])
{
error = TRUE; /* trailing empty */
found_zero = FALSE;
}else if(!cur_group) /* no groups, skip loop */
cur_group--;
for(; 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';

View File

@ -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]<CHAR_MAX)
groups[cur_group]++;
if(sep && groups_no<CHAR_MAX)
++groups_no;
}
}
if(sep && groups_no)
MSVCP_basic_string_char_append_ch(&groups_found, groups_no);
groups = MSVCP_basic_string_char_c_str(&groups_found);
if(cur_group && !groups[cur_group])
error = TRUE;
else if(!cur_group)
{
error = TRUE; /* trailing empty */
found_zero = FALSE;
}else if(!cur_group) /* no groups, skip loop */
cur_group--;
for(; 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]<CHAR_MAX)
groups[cur_group]++;
if(sep && groups_no<CHAR_MAX)
++groups_no;
}
}
if(sep && groups_no)
MSVCP_basic_string_char_append_ch(&groups_found, groups_no);
groups = MSVCP_basic_string_char_c_str(&groups_found);
if(cur_group && !groups[cur_group])
error = TRUE;
else if(!cur_group)
{
error = TRUE; /* trailing empty */
found_zero = FALSE;
}else if(!cur_group) /* no groups, skip loop */
cur_group--;
for(; 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';